R data.table::setDT()的keep.rownames参数不同写法下的行为差异咨询
原因解释
核心差异在于setDT是引用修改函数,和R中普通值语义函数的运行逻辑完全不同:
- 普通函数(比如你示例中的
mean)只会读取传入参数的值,不会修改参数本身,不管你传入的是变量还是表达式计算得到的临时值,只要能拿到数值就能正常计算。 setDT的设计目标是直接修改传入对象的内存内容,不需要额外赋值就能生效,因此它要求第一个参数是当前环境中已经存在的变量名,而非临时计算的匿名对象。
为什么第二种写法失效
当你执行setDT(dtcars <- copy(mtcars), keep.rownames=TRUE)时,R的执行顺序是:
- 先运行赋值表达式
dtcars <- copy(mtcars),将mtcars的副本绑定到当前环境的dtcars变量上 - 取赋值表达式的返回值(也就是
copy(mtcars)的一个临时副本)作为参数传给setDT setDT会把这个临时副本转成data.table,并按照要求添加行名列rn,但这个临时对象没有被任何变量绑定,执行完就被内存回收了- 你环境中
dtcars变量对应的原始对象完全没有被setDT触碰过,自然不会有rn列。
你写的显式函数调用形式setDT(<-(dtcars, copy(mtcars)), keep.rownames=TRUE)和上面的执行逻辑完全一致,传入setDT的始终是赋值表达式返回的临时副本,修改不会同步到环境中的dtcars变量。
替代的简化写法
如果你不想分两行写,可以直接捕获setDT的返回值赋值给变量,效果和两行写法完全一致:
dtcars <- setDT(copy(mtcars), keep.rownames = TRUE)
内容的提问来源于stack exchange,提问作者rg255
相关产品推荐
相关产品推荐

