根据向量中的值从数据框中选择行

时间:2012-07-23 12:08:49

标签: r subset r-faq

我的数据类似于:

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

的内容对数据进行过滤/子集化

3 个答案:

答案 0 :(得分:98)

查看?"%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),]

答案 1 :(得分:20)

与上述类似,使用filter中的dplyr

filter(df, fct %in% vc)

答案 2 :(得分:8)

另一种选择是使用键控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')data.frame转换为data.tabledata.frame的增强形式),fct列设置为关键字。
  • 接下来,您可以使用vc {/ 1}}将[J(vc)]向量进行子集化。

注意:当键是因子/字符变量时,您也可以使用setDT(dt, key = 'fct')[vc],但当vc是数字向量时,这将不起作用。如果vc是数字向量而未包含在J().()中,vc将作为行索引使用。

keys 和子集化概念的更详细解释可以在插图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]