data.table通过变量列表选列为何需with参数?其作用是什么?
with参数的疑问解答 先还原下你的场景,你定义了这样一个data.table对象:
dt <- data.table(V1=c(1L,2L), V2=LETTERS[1:3], V3=1:12)
直接用dt[, c("V1", "V2")]能正常选出前两列,但如果把列名存在变量里:
chosen.cols <- c("V1", "V2")
直接写dt[, (chosen.cols)]只会返回字符向量[1] "V1" "V2",必须加上with=F参数写成dt[, (chosen.cols), with = F]才能正常选取列。针对这两个问题,我来详细解释:
1)为何需要with参数?
这是因为data.table默认的with=TRUE行为,会把j位置的表达式当成在data.table自身的列环境中求值。简单说,默认情况下,你在j里写的内容,就像直接在一个只有data.table列变量的环境里写代码——比如你写dt[, V1],它会直接识别V1是data.table的列,返回该列的值。
那当你传入chosen.cols这个变量时,默认的with=TRUE会把它当成一个普通的表达式去求值,直接返回变量本身的内容(也就是字符向量c("V1","V2")),而不是去匹配data.table的列名。这时候就需要with=FALSE来改变这个逻辑,告诉data.table:“别把j里的内容当成表达式执行,就把它当成列名列表去匹配对应的列”。
2)with参数在代码中具体含义是什么?
with参数本质是控制j参数的求值逻辑,分两种情况:
with=TRUE(默认值):开启“列环境求值”模式。此时j中的表达式会在data.table的列变量环境中运行,你可以直接用列名作为变量进行计算,不用加$或者[[来引用列。比如:# 直接用列名做计算 dt[, sum(V3)] # 生成新列也很方便 dt[, V1_plus_V3 := V1 + V3]这种模式让data.table的语法更简洁,写起来像直接操作变量一样。
with=FALSE:切换到“列索引匹配”模式。此时j中的内容会被当成列名的字符向量、列的位置向量来处理,data.table会直接根据这个向量去选取对应的列,逻辑和base R中dt[, c("V1","V2")]一致。比如:# 用字符向量选列 chosen.cols <- c("V1", "V2") dt[, chosen.cols, with=FALSE] # 用位置向量选列也可以 dt[, c(1,2), with=FALSE]
内容的提问来源于stack exchange,提问作者Fabio Correa

