89

我有类似这样的数据:

dt <- structure(list(fct = structure(c(1L, 2L, 3L, 4L, 3L, 4L, 1L, 2L, 3L, 1L, 2L, 3L, 2L, 3L, 4L), .Label = c("a", "b", "c", "d"), class = "factor"), X = c(2L, 4L, 3L, 2L, 5L, 4L, 7L, 2L, 9L, 1L, 4L, 2L, 5L, 4L, 2L)), .Names = c("fct", "X"), class = "data.frame", row.names = c(NA, -15L))

我想根据fct变量中的值从此数据框中选择行。例如,如果我希望选择包含“a”或“c”的行,我可以这样做:

dt[dt$fct == 'a' | dt$fct == 'c', ]

产生

1    a 2
3    c 3
5    c 5
7    a 7
9    c 9
10   a 1
12   c 2
14   c 4

正如预期的那样。但是我的实际数据更复杂,我实际上想根据向量中的值选择行,例如

vc <- c('a', 'c')

所以我尝试了

dt[dt$fct == vc, ]

但这当然行不通。我知道我可以编写一些代码来循环遍历向量并拉出所需的行并将它们附加到新的数据框中,但我希望有一种更优雅的方式。

那么如何根据向量的内容过滤/子集我的数据vc呢?

4

3 回答 3

154

看看?"%in%"

dt[dt$fct %in% vc,]
   fct X
1    a 2
3    c 3
5    c 5
7    a 7
9    c 9
10   a 1
12   c 2
14   c 4

你也可以使用?is.element

dt[is.element(dt$fct, vc),]
于 2012-07-23T12:13:50.823 回答
35

与上面类似,使用filterfrom dplyr

filter(df, fct %in% vc)
于 2017-01-29T11:34:51.877 回答
15

另一种选择是使用 keyed data.table

library(data.table)
setDT(dt, key = 'fct')[J(vc)]  # or: setDT(dt, key = 'fct')[.(vc)]

这导致:

   fct X
1:   a 2
2:   a 7
3:   a 1
4:   c 3
5:   c 5
6:   c 9
7:   c 2
8:   c 4

这是做什么的:

  • setDT(dt, key = 'fct')将 a转换data.frame为 a data.table(这是 a 的增强形式data.frame),并将fct列设置为键。
  • 接下来,您可以只使用带有 的vc向量进行子集化[J(vc)]

注意:当键是因子/字符变量时,您也可以使用,但当是数字向量setDT(dt, key = 'fct')[vc]时,这将不起作用。vcWhenvc是一个数字向量并且没有包含在J()or中.()vc将作为 rowindex 工作。

可以在小插图Keys and fast binary search based subset中找到对键和子集概念的更详细说明。

@Frank 在评论中建议的替代方案:

setDT(dt)[J(vc), on=.(fct)]

vc包含不存在的值时dt,您需要添加nomatch = 0

setDT(dt, key = 'fct')[J(vc), nomatch = 0]

或者:

setDT(dt)[J(vc), on=.(fct), nomatch = 0]
于 2017-03-29T17:55:33.603 回答