Reputation: 71
I'm trying to create a loop (without the use of packages) to calculate the rows of an array. Each row of the matrix is calculated with one of the values of the previous row (in the code, the variable B
, from the second line, is the value of the C
variable of the previous line). My attempt is written below:
df=data.frame(matrix(ncol = 4, nrow = 5))
names(df)=c("A", "B", "C", "D")
for (i in 1:nrow(df){
df$A<-c(0, 0.25, 0.50, 0.75, 1.00)
df$B<-ifelse(df$A==0, 0, C[i-1])
df$C<-df$A*df$B)+1
df$D<-df$C+5
}
df
The expected result is:
A B C D
1 0.00 0.00 1.00 6.00
2 0.25 1.00 1.25 6.25
3 0.50 1.25 1.63 6.63
4 0.75 1.63 2.22 7.22
5 1.00 2.22 3.22 8.22
What am I doing wrong?
Upvotes: 0
Views: 692
Reputation: 28675
Inside the loop, you have to subset the columns to the row you're working on (row i
) for the given loop iteration. Otherwise you're doing assignment on the whole column each time and not just one row. Also, the creation of A and D don't need to be in the loop.
df$A <- c(0, 0.25, 0.50, 0.75, 1.00)
for(i in 1:nrow(df)){
df$B[i] <- ifelse(df$A[i] == 0, 0, df$C[i-1])
df$C[i] <- df$A[i]*df$B[i] + 1
}
df$D <- df$C + 5
You can also do this using Reduce
, but there's no consensus on whether this is any better, and many people will say using Reduce
with accumulate = T
is worse than just using a loop
df$A <- c(0, 0.25, 0.50, 0.75, 1.00)
df[, c('B', 'C')] <-
do.call(rbind,
Reduce(function(x, A) (A != 0)*x[2]*c(1, A) + 0:1,
df$A, init = c(0, 0), accumulate = T))[-1,]
df$D <- df$C + 5
Upvotes: 2