Creating a vector with cumulative sums after specific indices - r

I've got the following problem from my lector:
Make a vector which for each time y takes the value 5 shows the
cumulated sum of x values from the preceding position where y took the
value 5. 1 (Hint: use the commands cumsum() and diff().)
I'm not really sure in what format the vector in question is supposed to be formatted, so I propose two functions that give me the two different possible answers I can think of. Furthermore I don't understand in what way I'm supposed to use diff() instead I used a for-loop to tackle the problem:
# Creates random vectors
x <- round(runif(100,0,10))
y <- round(runif(100,0,10))
# X_,Y_ are arbitrary vectors of length n, and value decides what index from X_ is supposed to be chosen, as formulated in the question it is supposed to be 5.
# index is a vector that stores which entries of Y which has the value "value".
# Gives a vector as (x_1, x_(1+2),..., x_(sum(1,2...,index[1])))
test.cumsum <- function(X_,Y_, value){
index <- which(Y_ == value)
for(i in 1:length(index)){
if(i == 1){
z <- cumsum(x[1:index[1]])
}
if(i == length(index)){
break
}
else{
z <- c(z,cumsum(x[(index[i]+1):index[i+1]]))
}
}
z
}
# Gives a vector as (x_1+x_2...+index[1],x_(index[1]+1)+x_(index[1]+2)+...)
test.sum <- function(X_,Y_, value){
index <- which(Y_ == value)
for(i in 1:length(index)){
if(i == 1){
z <- sum(x[1:index[1]])
}
if(i == length(index)){
break
}
else{
z <- c(z,sum(x[(index[i]+1):index[i+1]]))
}
}
z
}
Is there any easier way to do this?

Related

While loop that stores values in a vector and stops when a value is already in the vector [R Programming]

I have a function, say fun(x), this function calculates a value and returns it. Then, using the returned value, run the function fun(x) with that value. I would like to code a while loop that uses this function, to generate values and store them in a vector, until the generated value from the function has already appeared in the vector.
This is what I have attempted.
x <-1 #initial value to run the function with
vec <-numeric(100) #create an empty vector to store the values
k <- 0 # have a counter for the vector position
while((fun(x) %in% vec) != TRUE){ #this while loop with run until the value from the function is already in the vector
k<- k+ 1 #increase counter
vec[k] <- fun(x) #run the function, store that value
x <- vec[k] #set x as the stored value
}
I cannot seem to figure out how to code this properly. Any help is appreciated
Something like this? Obviously sample() will return different numbers in the while statement than in the loop, but I assume your function isn't random?
sample(1:10,1)
vec <- c() ## empty vector
x=10
while(!sample(1:x,1) %in% vec){
x=sample(1:x,1)
vec <- c(vec,x)
}
Here is a way. It calls the function only once per iteration, saving its value in an auxiliary variable y. There is also a stop condition when the vector is full.
The function fun is an example meant for tests only returning one Poisson random number.
I have changed the starting value to x <- 10.
fun <- function(x) rpois(1, x)
x <- 10 # initial value to run the function with
n <- 100L # results vector length
vec <- numeric(n) # create an empty vector to store the values
k <- 0L # have a counter for the vector position
while(!((y <- fun(x)) %in% vec) && k < n){
k <- k + 1L
vec[k] <- y
x <- y
}
vec

R: Storing Loop Result in a Vector

I'm trying to run a loop that stores results in a vector. But I also need to increase the counter across a predetermined vector for the stored calculation to run properly. I'm stuck on two parts: (1) increasing the counter, and (2) storing the result of the loop in a vector.
I'm new to loops so bear with the most likely incorrect syntax below; here's what I'm working with:
x <- c(.01,.05,.10,.20,.25) # observed defect rates
for(i in x) {
j <- 1
if(x < 1){
atmost2[] <- dbinom(0,size=10,prob=x[[j]])+
dbinom(1,size=10,prob=x[[j]])+
dbinom(2,size=10,prob=x[[j]]) &&
j <- j + 1
}
}
atmost2
Essentially I'd like to store the result in a new vector, atmost2, with each successive loop running across the vector values in x by increasing j; j should increase to change the prob parameter in dbinom from the predetermined vector values in x.
Can anyone help out?
A few things:
juljo is correct to initialize the vector before a loop, and they made some other corrections, but I think their code only works if you have already established:
j <- 1
Without that, juljo's code breaks.
Also, your code doesn't need the '&&' to work. Just put j<-j+1 on a new line, like this (Using julgo's code)
j <- 1
x <- c(.01,.05,.10,.20,.25) # observed defect rates
atmost2 <- as.numeric(1:length(x)) # this initializes the vector to a predetermined length which may help with very large loops
for(i in 1:length(x)) {
if(x < 1){
atmost2[i] <- dbinom(0,size=10,prob=x[j])+ # note that the double brackets are gone
dbinom(1,size=10,prob=x[j])+
dbinom(2,size=10,prob=x[j])
}
j <- j + 1 # I think you want j to increment outside the if statement
}
atmost2
This code does 'something' but there are a few warnings and I'm not sure what you are trying to do.
You could also skip the adding of the dbinoms and instead to this:
j <- 1
x <- c(.01,.05,.10,.20,.25) # observed defect rates
atmost2 <- as.numeric(1:length(x)) # this initializes the vector to a predetermined length which may help with very large loops
for(i in 1:length(x)) {
if(x < 1){
atmost2[i] <- sum(dbinom( 0:2 , size=10,prob=x[j])) #dbinom will give a vector that can be summed
}
j <- j + 1 # I think you want j to increment outside the if statement
}
atmost2
But I think using the j iterator might be habit from other programming languages. Notice the same out put using a loop but without j:
x <- c(.01,.05,.10,.20,.25) # observed defect rates
atmost2 <- as.numeric(1:length(x)) # this initializes the vector to a predetermined length which may help with very large loops
for(i in 1:length(x)) {
if(x < 1){
atmost2[i] <- sum(dbinom(0:2,size=10,prob=x[i]))
}
}
atmost2
These all produce the same output:
> atmost2
[1] 0.9998862 0.9884964 0.9298092 0.6777995 0.5255928
But I have follow up questions:
Should atmost2 be the same length as x?
Are you using the values in x as probabilities? So, atmost2 is a sum of dbinom probabilities based on the value of x[i]?
Does it have to be a loop? R uses vectors very well, so the apply functions may be helpful. You might find lapply to be of use here.
?apply might start you off while
?lapply will give descriptions of the other apply functions.
So your code may look like this
x <- c(.01, .05, .10, .20, .25)
atmost2 <- as.numeric(1:length(x))
atmost2 <- lapply(x, function(x) sum(dbinom( 0:2 , size = 10, prob = x)))
atmost2 # this is a list, not a vector
the lapply function reads like this:
apply to items in a list, 'x', a function.
In this case, the function is an anonymous function "sum(dbinom....)"
So, apply to each value of x the function sum(dbinom...) and return a list.
Basically, it does the loop for you. And often times faster than a for-loop (in R).
If you need atmost2 to not be a list and instead a vector, you can:
unlist(atmost2)
> unlist(atmost2)
[1] 0.9998862 0.9884964 0.9298092 0.6777995 0.5255928
edit based on the reminder of Rui
Using sapply, everything else is the same but the output is indeed a vector.
x <- c(.01, .05, .10, .20, .25)
atmost2 <- as.numeric(1:length(x))
atmost2 <- sapply(x, function(x) sum(dbinom( 0:2 , size = 10, prob = x)))
atmost2 # this is a vector
How about calling elements like this:
x <- c(.01,.05,.10,.20,.25) # observed defect rates
atmost2 <- numeric() # Initialize vector before filling it in the loop
for(i in 1:length(x)) {
if(x[i] < 1){
atmost2[i] <- dbinom(0,size=10,prob=x[i])+
dbinom(1,size=10,prob=x[i])+
dbinom(2,size=10,prob=x[i])
}
}
atmost2

how to calculate h-point

I am trying to write a function to calculate h-point. the function is defined over a rank frequency data frame.
consider the following data.frame :
DATA <-data.frame(frequency=c(49,48,46,38,29,24,23,22,15,12,12,10,10,9,9), rank=c(seq(1, 15)))
and the formula for h-point is :
if {there is an r = f(r), h-point = r }
else { h-point = f(i)j-f(j)i / j-i+f(i)-f(j) }
where f(i) and f(j) are corresponding frequencies for ith and jth ranks and i and j are adjacent ranks that i<f(i) and j>f(j).
NOW, i have tried the following codes :
fr <-function(x){d <-DATA$frequency[x]
return(d)}
for (i in 1:length(DATA$rank)) {
j <- i+1
if (i==fr(i))
return(i)
else(i<fr(i) && j>fr(j)) {
s <-fr(i)*j-fr(j)*i/j-i+fr(i)-fr(j)
return(s)
}}
I also tried:
for (i in 1:length(DATA$rank)) {
j <- i+1
if (i==fr(i))
return(i)
if (i<fr(i) while(j>fr(j))) {
s <-fr(i)*j-fr(j)*i/j-i+fr(i)-fr(j)
return(s)
}}
and neither of them works. for the DATA ,the desired result would be i=11 and j=12, so:
h-point=12×12 - 10×11 / 12 - 11 + 12 - 10
can you please tell me what I`m doing wrong here?
You could do:
h_point <- function(data){
x <- seq(nrow(data))
f_x <- data[["frequency"]][x]
h <- which(x == f_x)
if(length(h)>1) h
else{
i <- which(x<f_x)
j <- which(x>f_x)
s <- which(outer(i,j,"-") == -1, TRUE)
i <- i[s[,1]]
j <- j[s[,2]]
cat("i: ",i, "j: ", j,"\n")
f_x[i]*j - f_x[j]*i / (i-j + f_x[i]-f_x[j])
}
}
h_point(DATA)
i: 11 j: 12
[1] 34
I think I have figured out what you are trying to achieve. My loop will go through DATA and break at any point if rank == frequency for a given row. If might be more prudent to explicitly test this with DATA$rank[i] == fr(i) rather than relying on i, in case tied ranks etc.
The second if statement calculates h-point (s) for rows i and j if row i has rank that is lower than freq and row j has a rank that is higher.
Is this what you wanted?
DATA <-data.frame(frequency=c(49,48,46,38,29,24,23,22,15,12,12,10,10,9,9), rank=c(seq(1, 15)))
fr <-function(x){d <-DATA$frequency[x]
return(d)}
for(i in 1:nrow(DATA)){
j <- i+1
if (i==fr(i)){
s <- list(ij=c(i=i,j=j), h=i)
break
}else if(i <fr(i) && j>fr(j)){
s <-list(ij=c(i=i,j=j),h=fr(i)*j-fr(j)*i/j-i+fr(i)-fr(j))
}}
I am not sure the formula is correct, in your loop you had j-i but in explanation it was i-j. Not sure if the entire i-j+fr(i)-fr(j) is the denominator and similarly for the numerator. Simple fixes.

How to store values in a vector inside a while loop in R

For the next exercise: From a certain numerical value, check if this is a natural number or not so that, if it is, it shows the divisors of this number and, if it is not, it shows an error message.
As there was no predefined function for this I wrote:
n <- 102
x <- n
res <- c()
while (x>0){
if (n%%x == 0){
res[x] <- x
x = x-1
} else {
x = x -1
} print("The values are ", res)
}
res
Works nice, except it´s not storing the values inside the vector. Any ideas?
I´m new to programming and stackoverflow. I hope this question is right posted and presented.
Cheers
What you need is a counter "i" to save the value in the next entry of the vector
n <- 102
x <- n
res <- c()
i<-1
while (x>0){
if (n%%x == 0){
res[i] <- x
x = x-1
i<-i+1
} else {
x = x -1
}
}
res

For-Loop in R with if-else: How to save the output

I am trying to save the output of the code below. I know "print" is the problem, but I do not know what works instead.
I generally wonder if there is not another way instead of the for-loop: For each value in the vector (x), I want to draw a new random number (here with runif) and match it to a given value (here for example 0.5). Depending on the result, a new value for x should be stored in a vector x2 (similar to the if-else example below). Waiving the for-loop, I could not find a way to always draw a new random number for each value in vector x.
I would be very grateful for any help!
x <- c(2,2,2,3,3,3)
for(i in x){
if(runif(1) <= 0.5){
print(i + 1)
} else {
print(i)
}
}
Or you could use lapply, then you don't have to modify an object outside your loop each step.
x <- c(2,2,2,3,3,3)
x2 <- unlist(lapply(x, function(x){
if(runif(1) <= 0.5) return(x +1)
return(x)
}))
x2
Try this code:
x <- c(2,2,2,3,3,3)
x2<-NULL
for(i in 1:length(x)){
if(runif(1) <= 0.5){
x2[i]<-1
} else {
x2[i]<-2
}
}
Your output
x2
[1] 1 2 2 1 2 1
In x2 you have random numbers with given values (1 and 2) related to the runif probability.
This is the same thing in a single row:
ifelse(runif(n = length(x))<=0.5,1,2)
[1] 1 2 2 2 1 1

Resources