Let's say that I am working with the following data.
library(tidyverse)
df_temp<-iris%>%
select(!Species)
leng=2
for (j in 1:leng) {
df<-data.frame(matrix(NA, nrow = dim(df_temp)[1], ncol=leng))
#df<-array(NA, dim=c(dim(df_temp)[1], leng, 1))
df[,j]<-df_temp[,j] / df_temp[, (j leng) ]
}
when I run the for
loop only the last index is shown. I have tried to use the ´df´ as array, but I have the same problem. The only solution that I found was define the columns at the beginning.
df<-tibble(
c1= rep(NA, nrow(df_temp)),
c2= rep(NA, nrow(df_temp))
)
for (j in 1:leng) {
df[,j]<-df_temp[,j] / df_temp[, (j leng) ]
}
The problem is that in my original df I have 180 columns and I can not create manually all the columns.
CodePudding user response:
Instead of creating a data.frame object, create a NULL list
and update inside the loop
df_list <- vector('list', leng)
names(df_list) <- paste0("c", seq_along(df_list))
for (j in 1:leng) {
df_list[[j]]<-df_temp[,j] / df_temp[, (j leng) ]
}
The list
can be converted to a data.frame/tibble/matrix
etc either using cbind
with do.call
(or just use bind_cols
from dplyr
i.e. dplyr::bind_cols(df_list)
out <- do.call(cbind.data.frame, df_list)
-output
> head(out)
c1 c2
1 3.642857 17.50
2 3.500000 15.00
3 3.615385 16.00
4 3.066667 15.50
5 3.571429 18.00
6 3.176471 9.75
If the computation is as showed in the post, it can be easily done without a loop as well
head(df_temp[1:2]/df_temp[3:4])
Sepal.Length Sepal.Width
1 3.642857 17.50
2 3.500000 15.00
3 3.615385 16.00
4 3.066667 15.50
5 3.571429 18.00
6 3.176471 9.75
CodePudding user response:
You are initializing a new df
every time it loops. You can solve this easily in your current code by just moving the df
argument outside the loop:
leng=2
df <- data.frame(matrix(NA, nrow = dim(df_temp)[1], ncol = leng)) #move outside the loop
for (j in 1:leng) {
df[, j] <- df_temp[, j] / df_temp[, (j leng)]
}
Output:
head(df)
# X1 X2
#1 3.642857 17.50
#2 3.500000 15.00
#3 3.615385 16.00
#4 3.066667 15.50
#5 3.571429 18.00
#6 3.176471 9.75