我正在尝试通过从data.table中选择一些列来对数据集进行子集化.但是,我的代码不适用于某些变体.
这是一个示例data.table
library(data.table) DT <- data.table( ID = 1:50, Capacity = sample(100:1000, size = 50, replace = F), Code = sample(LETTERS[1:4], 50, replace = T), State = rep(c("Alabama","Indiana","Texas","Nevada"), 50))
这是一个有效的子集代码:
DT[ , 1:2]
这是一段不起作用的代码.请注意,这适用于数据框,但不适用于data.table.
DT[ , seq(1:2)]
我需要第二种格式的东西,因为我是基于grep()的输出进行子集化,它提供与第二种格式相同的输出.我做错了什么?
谢谢!
我学到的教训是使用list
而不是c
:
DT[ ,list(ID,Capacity)] #--------------------------- ID Capacity 1: 1 483 2: 2 703 3: 3 924 4: 4 267 5: 5 588 --- 196: 46 761 197: 47 584 198: 48 402 199: 49 416 200: 50 130
它可以让你忽略那些令人讨厌的引用,它也会让你朝着将j
参数视为具有数据表本身环境的计算表达式的方向移动.
要按编号"获取"命名列,请使用mget
函数和names
函数.R'名称'是语言元素,即来自当前环境的搜索路径中的数据对象.dataframes的列名不其实- [R names
.因此,您需要一个具有字符值的函数,并使解释器将其视为完全限定的name
.数据表 - [ - j项的函数语法确实将列名称作为语言对象处理,而不是像[.data.frame
-function 那样处理字符值:
DT[ ,mget(names(DT)[c(1,2)])] ID Capacity 1: 1 483 2: 2 703 3: 3 924 4: 4 267 5: 5 588 --- 196: 46 761 197: 47 584 198: 48 402 199: 49 416 200: 50 130
在最新版本的data.table中,可以使用数字j
指定列。此行为包括诸如DT[,1:2]
指定列的数字范围的格式。(请注意,此语法不适用于较旧的data.table版本)。
那么为什么DT[ , 1:2]
有效,却DT[ , seq(1:2)]
没有呢?答案埋在的代码中data.table:::[.data.table
,其中包括以下几行:
if (!missing(j)) { jsub = replace_dot_alias(substitute(j)) root = if (is.call(jsub)) as.character(jsub[[1L]])[1L] else "" if (root == ":" || (root %chin% c("-", "!") && is.call(jsub[[2L]]) && jsub[[2L]][[1L]] == "(" && is.call(jsub[[2L]][[2L]]) && jsub[[2L]][[2L]][[1L]] == ":") || (!length(all.vars(jsub)) && root %chin% c("", "c", "paste", "paste0", "-", "!") && missing(by))) { with = FALSE }
我们可以看到这里data.table
是自动设置的with = FALSE
,当它检测到使用功能参数你:
在j
。它没有为内置的功能seq
,因此with = FALSE
如果要使用seq
语法,则必须指定自己。
DT[ , seq(1:2), with = FALSE]