You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在R的data.table中通过关联其他表的函数新增列失败求助

问题描述

我有一个data.table,想通过以下方式新增一列:

big_table[, ("new_column") := some_function(col1, col2, …)]

自定义函数some_function用于从另一个小表small_table中按条件匹配并提取动态列,单独调用这个函数时正常,但给big_table新增列时失败。

第一种写法报错:

Error in `big_table[, ("new_column") := some_function(col1 : 
  Supplied 588 items to be assigned to 116588 items of column 'new_column'. If you wish to 'recycle' the RHS please use rep() to make this intent clear to readers of your code.

第二种写法报错:

Error in .subset2(x, i, exact = exact) : 
  recursive indexing failed at level 2

推测是动态列查找导致的问题,请求修复。以下是简化示例:

# 参考表:code对应不同年龄段的数值
supplement <- data.table(code = c("male", "female"),
                         child = c(1, 2),
                         adult = c(3, 4))

# 主表:A列包含code前缀,B列是年龄段
DT <- data.table(A = c("male1", "male2", "male3", "female1", "female2"),
                 B = c("child", "child", "adult", "adult", "child"))

# 期望得到的结果
desired_result <- data.table(A = c("male1", "male2", "male3", "female1", "female2"),
                             B = c("child", "child", "adult", "adult", "child"),
                             sup = c("1", "1", "3", "4", "2"))

解决方案

方法1:转长表+连接(推荐,data.table原生高效写法)

核心思路是先把宽格式的supplement转成长格式,再和主表通过匹配字段连接,这是data.table最擅长的批量操作,效率远高于逐行处理:

library(data.table)

# 将supplement转长表,统一匹配字段
supplement_long <- melt(supplement, id.vars = "code", 
                        variable.name = "B", value.name = "sup")

# 从DT$A中提取code前缀(如"male1"提取为"male")
DT[, code := sub("\\d+$", "", A)]

# 按code和B列连接,批量赋值sup列
DT[supplement_long, sup := i.sup, on = .(code, B)]

# 可选:删除临时生成的code列
DT[, code := NULL]

方法2:修复自定义函数(支持向量输入)

如果一定要用自定义函数,需让函数支持向量输入,避免因返回结果长度不匹配报错。可以用mapply或Vectorize实现逐元素处理:

# 定义处理单个元素的函数
get_sup <- function(a, b) {
  code <- sub("\\d+$", "", a)
  supplement[code == code, get(b)]
}

# 用mapply逐行调用函数赋值
DT[, sup := mapply(get_sup, A, B)]

# 或者用Vectorize包装函数,直接向量调用
vec_get_sup <- Vectorize(get_sup)
DT[, sup := vec_get_sup(A, B)]

方法3:逐行处理(适合理解,大表不推荐)

通过by = .I实现逐行运算,适合小表调试,大表性能不如连接方法:

DT[, sup := {
  code <- sub("\\d+$", "", A)
  supplement[code == code, get(B)]
}, by = .I]

错误原因解析
  • 第一个错误:自定义函数未处理向量输入,返回结果长度(588)远小于主表行数(116588),导致赋值时长度不匹配。
  • 第二个错误:动态列查找(如get(b))时,b是向量而非单个值,直接调用会触发递归索引失败。

内容的提问来源于stack exchange,提问作者scenario

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 20:55:10