如何在data.table的j运算符(:=)中用链式引用修改底层表
如何在data.table的
:=中用链式操作修改原数据表? 嘿,我来帮你理清这个问题~首先得拆解下你当前代码的问题:
你写的这段代码:
dt[letters=="A"][,numbers := numbers/2]
第一个dt[letters=="A"]会返回一个原数据表的子集副本(data.table默认在链式操作里,提取子集后再操作的话,是在副本上修改,不会影响原表),所以你这里修改的只是那个临时的子集,原dt根本没变化;而dt2就是那个被修改后的子集副本。
下面给你两种正确的处理方式:
方法1:单步完成筛选+修改(推荐,最符合data.table高效风格)
data.table的设计初衷就是让你把筛选(方括号的i部分)和修改(j部分)放在同一个方括号里,这样是原地修改原表,不需要链式,效率拉满:
dt[letters == "A", numbers := numbers / 2]
执行完这句,原dt里所有letters为"A"的行,numbers都会直接减半,完全不需要额外赋值。
方法2:特殊场景下的链式修改(不推荐,仅作参考)
如果因为业务逻辑必须用链式操作(比如先做了一些中间转换再修改),那得确保修改的是原表的引用,而不是副本。可以借助data.table的特殊变量.I(代表当前子集在原表中的行索引)来实现:
dt[letters == "A"][, dt[.I, numbers := numbers / 2]]
这里.I会拿到前一步筛选出的行在原表中的位置,然后直接对原表对应行做修改。不过这种写法不如方法1简洁高效,非必要不建议用。
验证修改结果
执行完修改后,直接查看原表的对应行就能确认:
dt[letters == "A"]
内容的提问来源于stack exchange,提问作者Gompu
相关产品推荐
相关产品推荐

