data.table连接时如何用字符向量批量引用列实现多列赋值
在data.table连接中批量动态赋值多列的正确方法
你遇到的问题核心在于get()函数只能处理单个对象名,当传入长度大于1的字符向量时,它只会读取第一个元素的值并重复赋值给所有目标列——这就是为什么b_t1被错误地赋值为i.a的100,而非预期的i.b的2。
不用依赖eval(parse(...))这种可读性极差的写法,我们可以用两种更简洁的方式实现批量赋值:
方法1:使用mget()批量获取列
mget()可以接收字符向量,一次性取出所有对应的对象,完美适配多列赋值的需求:
dt1 <- data.table(id = c(1,2), year = c(2001, 1999)) dt2 <- data.table(year = c(2001, 2002, 1998, 1999), id = c(1,1,2,2), a=c(50, 100, 30, 22), b=c(1,2,3,4)) cols <- c("a", "b") t <- 1 dt1[, match_year := year + 1] # 正确的批量赋值代码 dt1[dt2, on = .(id, match_year = year), (paste0(cols, "_t", t)) := mget(paste0("i.", cols))][]
方法2:使用lapply() + get()循环获取列
如果更习惯get()的用法,也可以用lapply()遍历生成的i.前缀列名,逐个调用get():
dt1[dt2, on = .(id, match_year = year), (paste0(cols, "_t", t)) := lapply(paste0("i.", cols), get)][]
执行结果验证
运行后dt1会得到符合预期的结果:
id year match_year a_t1 b_t1 1: 1 2001 2002 100 2 2: 2 1999 2000 NA NA
为什么原始方法失效?
你的代码get(paste0("i.", cols))中,paste0("i.", cols)生成的是c("i.a", "i.b"),但get()只会处理第一个元素"i.a",然后把这个值重复分配给所有目标列(a_t1和b_t1),这就导致了错误的赋值结果。而mget()或lapply()能正确处理多个列名的批量获取。
内容的提问来源于stack exchange,提问作者adamski
相关产品推荐
相关产品推荐

