R:create new column and value using lapply & apply nested on data.frame list, wrong output
apply, dataframe, r
Solution
There are a couple of problems with your approach. First one is that you are modifying `dfx` from your innermost apply, but you are doing it with a simple `<-` operator instead of the `<<-` operator. The former operator will not affect things outside of a function's scope. I would also not advocate using `<<-` (see solution here for alternate).
The other issue you have is that you are not specifying what row of the `dfx` to update inside `apply`, so even if you had the `<<-` every row would get updated and you would end up with the final value being whatever the last test comparison produced.
Finally, you are returning the result of the `apply` instead of the modified `dfx` in your `lapply`.
Here, we apply the `transform` function to each data frame to add a `factor` column based on the values of the 3rd and 4th columns in the data frames (referenced here by name). Notice how I was able to use `ifelse` to avoid the inner `apply`:
lapply(dflist, transform, factor=ifelse(X4x < X6x, "nonNA", "NA"))
# $df1
# var X2x X4x X6x factor
# 1 101337 4.631833 4.4547 11.09733 nonNA
# 2 345754 3.727433 10.8560 10.53660 NA
#
# $df2
# var X2x X4x X6x factor
# 1 101337 5.631833 10.4547 11.09733 nonNA
# 2 345754 5.727433 12.8560 10.53660 NA
Here is an unnecessary variation that hews closer to what you were trying to do, for compare/contrast and hopefully so you can see more clearly why yours wasn't working:
lapply(dflist,
function(dfx) {
dfx$factor <- ""
lapply(1:nrow(dfx),
function(row.id) {
dfx[row.id, "factor"] <<-
if(dfx[row.id, 3] < dfx[row.id, 4]) "nonNA" else "NA"
} )
dfx
} )
Notice how I `lapply` in the inner loop instead of `apply` so that I can keep track of the row numbers. Again, I do not recommend this approach, but it is here for explanatory purposes.
Problem
I have a list of data frames (here 2 as example). ``` df1 <- read.table(text= "var,X2x,X4x,X6x 101337,4.631833,4.4547,11.097333 345754,3.727433,10.8560,10.536600" ,header=TRUE, sep=",") df2 <- read.table(text= "var,X2x,X4x,X6x 101337,5.631833,10.4547,11.097333 345754,5.727433,12.8560,10.536600" ,header=TRUE, sep=",") dflist <- list(df1=df1, df2=df2) ``` I wanted to use lapply to go through each data.frame and the use apply to do a simple comparison (i.e, check if the value from the second column is greater than the third one), given the result, add a new column with a tag (in the example then new column is called "factor".) I'm almost there but The output of my script is wrong, returning a list of vectors instead of a list of data.frames with the added column. here is the code: ``` dfL <- lapply(dflist,function(dfx) { apply(dfx,1, function(df) { if(df[3] < (df[4] )) { dfx$factor<-"nonNA"} else {dfx$factor<-"NA"} } ) } ) ``` Could you please explain me what I'm doing wrong?