R data.table自定义函数多次运行出现输出结果累加异常问题
问题原因
这个问题的核心是data.table包的**原地修改(按引用更新)**特性,:=操作符不会生成数据副本,会直接修改传入的原始变量。
具体运行逻辑拆解
你定义的try_1函数第一行执行了in_b[, :=(Vb = Vb/1000)],这里的in_b是全局环境中dt_b的引用,不是独立副本,每次调用函数都会直接修改全局的dt_b的Vb值:
- 第一次调用函数:
dt_b初始Vb值为1000、2000,除以1000后变为1、2,计算得到value = 2/1=2、5/2=2.5,符合预期 - 第二次调用函数:
dt_b的Vb已经是1、2,再次除以1000变为0.001、0.002,计算得到value = 2/0.001=2000、5/0.002=2500 - 第三次调用函数:
dt_b的Vb变为0.000001、0.000002,计算得到value = 2000000、2500000,和你观测到的结果完全一致
另外你代码里的tmp <- in_a也存在相同隐患:tmp是dt_a的引用,执行tmp[, value := Va/in_b$Vb]会直接给全局的dt_a新增value列,只是你的场景中未修改Va的值,所以没有影响最终输出结果。
修复方案
有两种常用修复方式:
- 显式生成数据副本,避免修改原始变量:
try_1 <- function(in_a, in_b){ # 先拷贝in_b再修改,不影响原变量 in_b <- copy(in_b)[, `:=`(Vb = Vb/1000)] # 拷贝in_a再做修改 tmp <- copy(in_a) tmp[, value := Va/in_b$Vb] return(tmp) }
- 直接在计算环节做单位换算,不修改
in_b:
try_1 <- function(in_a, in_b){ tmp <- copy(in_a) tmp[, value := Va/(in_b$Vb/1000)] return(tmp) }
内容的提问来源于stack exchange,提问作者T X
相关产品推荐
相关产品推荐

