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'

谁能帮我理解为什么这个方法不起作用

dt[cols=='a']

但是这个可以吗?

dt[get(cols)=='a']

两种方法不应该在vec中返回相同的东西?

Akrun已经提供了一个有用的解决方案,所以我将提供诊断.

过滤data.table

按照您的意愿过滤dt,data.table需要一个整个向量十的logical值,对应于dt中的10行,用于指示保留哪些行(TRUE)和丢弃哪些行(FALSE)。因此,当您过滤dt时,必须在[括号中包含这样一个逻辑向量(或求值为它的东西)。下面是一个人为的例子:

dt[c(TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE)]

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

id amount id2
1:  a      1   a
2:  d      4   a
3:  e      5   a
4:  g      7   b

cols为什么失败

由于colscharacter值为'id'

cols <- 'id'

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

dt[cols == 'a']
# ...is the same as...
dt['id' == 'a']
# ...is the same as...
dt[FALSE]

这只提供了一个单个logical值(FALSE),而不是data.table真正需要的十个logical值的向量

。结果是data.table省略了所有

Empty data.table (0 rows and 3 cols): id,amount,id2

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

get(cols)为什么有效

当你使用get('my_variable')时,你告诉R "get"从周围环境中获取my_variable的值。如果在dt上的[操作中运行get()

dt[get(# ...
]

R将根据给定名称在dt中搜索列,并返回该列(一个向量)作为get()的值。因此,在此上下文中使用get('id')将在dt中得到id列,这是向量

c('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j')
# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"

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

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)]

这给了我们以下data.table中过滤的结果:

id amount id2
1:  a      1   a

我们可以在symbol上使用eval

dt[eval(as.name(cols)) == 'a']
id amount id2
1:  a      1   a
或者指定.SDcols
dt[dt[, .SD[[1]] == 'a', .SDcols = cols]]
id amount id2
1:  a      1   a

或直接子集.SD,如果只有一个列

dt[dt[, .SD[[cols]] == 'a']]
id amount id2
1:  a      1   a

首选的方法是通过.SDcols,因为get有时会有环境问题,而eval(不被社区推荐)

最新更新