data.table链式操作中使用:=新增列不生效如何解决?
data.table链式操作
:=不生效问题解答 产生原因
data.table的:=是按引用修改的运算符,仅会修改它所直接作用的data.table对象:
- 链式写法
aa[order(a,b)][, c:=cumsum(a), by=.(b)]中,第一个aa[order(a,b)]会生成一个临时的未命名副本,后续的:=仅修改了这个临时副本,运行结束后临时副本会被自动回收,原对象aa没有被修改,因此看不到新增的c列。 - 拆分写法中
:=直接作用于原对象aa,因此会直接修改原对象新增c列。 - 赋值给
bb的写法是将修改后的临时副本存储为新对象bb,因此bb存在c列,但原对象aa仍然没有变化。
正确的实现方式
方案1:合并操作到单组中括号(推荐,直接修改原对象)
将排序逻辑放在中括号的i位置,赋值逻辑放在j位置,:=会直接作用于原对象aa:
aa <- data.table(a=c(1,2,3), b = c("a","b","b")) aa[order(a,b), c := cumsum(a), by = .(b)]
方案2:先使用setorder排序(修改原对象排序)再赋值
如果需要永久修改原对象的排序,可以先用setorder按引用排序,再做赋值操作:
aa <- data.table(a=c(1,2,3), b = c("a","b","b")) setorder(aa, a, b) aa[, c := cumsum(a), by=.(b)]
方案3:多步链式操作后赋值回原对象
如果确实需要多步链式处理(如多步筛选、转换后再赋值),将整个链式操作的结果赋值回原对象即可:
aa <- data.table(a=c(1,2,3), b = c("a","b","b")) # 多步链式操作示例,末尾的[]可选,用于触发结果打印 aa <- aa[order(a,b)][, c := cumsum(a), by=.(b)][, d := a*2][]
内容的提问来源于stack exchange,提问作者Kallas
相关产品推荐
相关产品推荐

