为什么列名向量不能用于过滤 data.table 中的行?

R. *_*boy 2 r data.table

假设我有以下数据dt和列名向量cols

dt <- data.table(id = letters[1:10], amount = 1:10, id2 = c(rep('a',5),rep('b',5)))
cols <- 'id'
Run Code Online (Sandbox Code Playgroud)

有人可以帮助我理解为什么这种方法不起作用

dt[cols=='a']
Run Code Online (Sandbox Code Playgroud)

但这有效吗?

dt[get(cols)=='a']
Run Code Online (Sandbox Code Playgroud)

两种方法不应在vec?中返回相同的内容。

Gre*_*reg 7

Akrun已经为您的问题提供了有用的解决方案,因此我将提供诊断

过滤data.table

dt要按照您的意图进行过滤,data.table需要一个由十个值组成的完整向量,对应于 中的十行,以指示要保留哪些行 ( ) 以及要丢弃哪些行 ( )。因此,当您过滤 时,您必须在括号内包含这样一个逻辑向量(或对其求值的东西)。这是一个人为的例子: logicaldtTRUEFALSEdt[

dt[c(TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE)]
Run Code Online (Sandbox Code Playgroud)

这将为我们提供以下过滤结果data.table

   id amount id2
1:  a      1   a
2:  d      4   a
3:  e      5   a
4:  g      7   b
Run Code Online (Sandbox Code Playgroud)

为什么cols失败

由于cols有一个character值为'id'

cols <- 'id'
Run Code Online (Sandbox Code Playgroud)

那么比较cols == 'a'与比较是一样的'id' == 'a',这显然是FALSE

dt[cols == 'a']
# ...is the same as...
dt['id' == 'a']
# ...is the same as...
dt[FALSE]
Run Code Online (Sandbox Code Playgroud)

这仅提供单个 logical值 ( FALSE),而不是过滤真正需要的十个值的向量。 logicaldata.table

结果是data.table省略了所有内容

Empty data.table (0 rows and 3 cols): id,amount,id2
Run Code Online (Sandbox Code Playgroud)

与 相比dt[TRUE],它包括所有内容:

    id amount id2
 1:  a      1   a
 2:  b      2   a
 3:  c      3   a
 4:  d      4   a
 5:  e      5   a
 6:  f      6   b
 7:  g      7   b
 8:  h      8   b
 9:  i      9   b
10:  j     10   b
Run Code Online (Sandbox Code Playgroud)

为什么get(cols)有效

当您使用 时,您是在告诉 R从周围环境中get('my_variable')“获取” 的值。my_variable如果您get()[以下操作中运行dt

dt[get(# ...
   ]
Run Code Online (Sandbox Code Playgroud)

R 将按dt给定名称在其中搜索列,并将返回该列(向量)作为 的值get()。因此,在这种情况下使用将为您提供中get('id')的列,它是向量iddt

c('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j')
# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
Run Code Online (Sandbox Code Playgroud)

现在我们把它们放在一起:

dt[get(cols) == 'a')
# ...is the same as...
dt[get('id') == 'a')
# ...is the same as...
dt[c('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j') == 'a']
# ...is the same as...
dt[c(TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE)]
Run Code Online (Sandbox Code Playgroud)

这为我们提供了以下过滤结果data.table

   id amount id2
1:  a      1   a
Run Code Online (Sandbox Code Playgroud)