0
votes

I am trying to use an lapply that takes two lists of columns into account (all are numeric type) in what would seem to be a simple line of code, but the output is not as expected.

This is my code :

x<-50

measure <- c("haz", "waz", "whz", "htcm", "wtkg", "bmi")
new_measure_1.5 <- paste(measure, "1.5", sep = "_")
new_temp_cols<-paste("temp", new_measure_1.5, sep = "_")
new_columns<-paste(new_measure_1.5, "1", sep="_")

newcols_1.5_months<-function(x, agedays, new_temp_cols, y){
    ifelse(agedays==x, new_temp_cols, y)
  }

DT[, (new_columns) := lapply(.SD, function(y) newcols_1.5_months(x, agedays, new_temp_cols, y)), .SDcols = new_columns ]

The above code results in new_columns (haz_1.5_1, waz_1.5_1, whz_1.5_1, wtkg_1.5_1, htcm_1.5_1, bmi_1.5_1) holding the names of the columns in the list new_temp_cols (temp_haz_1.5, temp_waz_1.5, temp_whz_1.5, temp_wtkg_1.5, temp_htcm_1.5, temp_bmi_1.5) as opposed to the values they hold in my data table. It seems that R is reading the list as a vector of strings rather than a vector of columns. Why is this?

I've tried using multiple .SDcols, but this doesn't work :

DT[, (new_columns) := lapply(.SD, function(y) newcols_1.5_months(x, agedays, new_temp_cols, y)), .SDcols = c(new_columns, new_temp_cols) ]

Is there a simple fix to this?

**** Editing to add a small subset of dummy data similar to my data table

measure<-c("haz", "waz")
new_measure_1.5 <- paste(measure, "1.5", sep = "_")
new_temp_cols<-paste("temp", new_measure_1.5, sep = "_")
new_columns<-paste(new_measure_1.5, "1", sep="_")


anthro <- data.table

    (agedays = c(25,50,53,22,37,50,12,45,50,15,33,50),
                               temp_haz_1.5 = c(1.2,1.5,1.7,2.0,4.5,6.7,6.8,6.7,4.5,6.6,8.9,6.7),
                               temp_waz_1.5 = c(3.2,1.8,6.7,2.8,3.5,7.7,9.8,1.7,6.9,3.8,0.9,4.7),
                   haz_1.5_1 = c(1.2,2.5,4.7,7.0,4.7,6.8,6.3,2.7,5.5,8.6,3.9,6.7),  
                   waz_1.5_1 =c(6.2,2.5,5.7,7.0,2.5,7.7,8.8,9.7,2.5,4.6,5.9,6.7))
1
(1) You mention new_measure_3.5 but define new_measure_1.5, typo? (2) new_columns explicitly contains those names, so it makes sense that data.table would keep these. Sample data will be informative here. - r2evans
@r2evans yes it is a typo! Sorry, that's embarrassing. I just edited my post to fix that. Thanks for pointing it out. - bziggy
@akrun Just edited the post to add in some dummy data - bziggy
can you please check my code below - akrun

1 Answers

1
votes

If we have multiple columns, then use Map to loop over each of the corresponding sets of columns and apply the function.

library(data.table)
x <- 50
DT[, (new_columns) := Map(function(u, y) 
    newcols_1.5_months(u, DT[['agedays']], x, y),
    .SD[, new_columns, with = FALSE], 
       .SD[, new_temp_cols, with = FALSE]) ]

Perhaps the function can be

newcols_1.5_months<- function(u, agedays, x,  y){
      ifelse(agedays==x, u, y)
   }

data

DT <- data.table(agedays = c(25,50,53,22,37,50,12,45,50,15,33,50),
                               temp_haz_1.5 = c(1.2,1.5,1.7,2.0,4.5,6.7,6.8,6.7,4.5,6.6,8.9,6.7),
                                temp_waz_1.5 = c(3.2,1.8,6.7,2.8,3.5,7.7,9.8,1.7,6.9,3.8,0.9,4.7),
                    haz_1.5_1 = c(1.2,2.5,4.7,7.0,4.7,6.8,6.3,2.7,5.5,8.6,3.9,6.7),  
                    waz_1.5_1 =c(6.2,2.5,5.7,7.0,2.5,7.7,8.8,9.7,2.5,4.6,5.9,6.7))