Home > other >  How to create a for loop for this command in R?
How to create a for loop for this command in R?

Time:11-08

I have data similar to this:

library(data.table)
library(stringr)

dt <- data.table(id=1:20,
           month_1=rep(sample(1:12, 20, replace = T)),
           month_2=rep(sample(1:12, 20, replace = T)),
           month_3=rep(sample(1:12, 20, replace = T)),
           month_4=rep(sample(1:12, 20, replace = T)),
           year_1=rep(sample(2010:2020, 20, replace = T)),
           year_2=rep(sample(2010:2020, 20, replace = T)),
           year_3=rep(sample(2010:2020, 20, replace = T)),
           year_4=rep(sample(2010:2020, 20, replace = T)))

and I am trying execute these 4 commands

dt[,date_1:= as.Date(paste0(year_1, "-", str_pad(month_1, 2, pad = "0"), "-", 01))]
dt[,date_2:= as.Date(paste0(year_2, "-", str_pad(month_1, 2, pad = "0"), "-", 01))]
dt[,date_3:= as.Date(paste0(year_3, "-", str_pad(month_1, 2, pad = "0"), "-", 01))]
dt[,date_4:= as.Date(paste0(year_4, "-", str_pad(month_1, 2, pad = "0"), "-", 01))]

How can I do this using a for loop?

I have tried:

for (i in 1:4){
  dt[,date_i:= as.Date(paste0(year_i, "-", str_pad(month_i, 2, pad = "0"), "-", 01))]
}

But get the error:

Error in paste0(year_i, "-", str_pad(month_i, 2, pad = "0"), "-", 1) : object 'year_i' not found

CodePudding user response:

Fixing the broken loop without major changes:

for (i in 1:4) {
  date_var  = paste0("date_", i)
  year_var  = paste0("year_", i)
  month_var = paste0("month_", i)
  dt[, (date_var) := as.Date(paste0(get(year_var), "-", str_pad(get(month_var), 2, pad = "0"), "-", 01))]
}

Refactoring a bit and removing the stringr dependency:

for (i in 1:4) {
  year_var  = paste0("year_", i)
  month_var = paste0("month_", i)
  set(
    x     = dt, 
    j     = paste0("date_", i), 
    value = as.Date(paste(dt[[year_var]], dt[[month_var]], "1"), "%Y %m %d")
  )
}

CodePudding user response:

Or with lapply:

i <- 1:4
dt[,paste0("date_i",i):=lapply(i,function(i) as.Date(paste0(get(paste0("year_",i)), "-", str_pad(month_1, 2, pad = "0"), "-", 01)))][]

CodePudding user response:

One way to solve your problem:

i = 1:4

dt[, paste0("date_", i) := Map(\(x,y) as.Date(sprintf("%d-d-01", x, y)),
                               mget(paste0("year_", i)),
                               mget(paste0("month_", i)))]  
  • Related