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

Joe*_*ing 59 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))
Run Code Online (Sandbox Code Playgroud)

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

dt[dt$fct == 'a' | dt$fct == 'c', ]
Run Code Online (Sandbox Code Playgroud)

产量

1    a 2
3    c 3
5    c 5
7    a 7
9    c 9
10   a 1
12   c 2
14   c 4
Run Code Online (Sandbox Code Playgroud)

正如所料.但是我的实际数据更复杂,我实际上想要根据矢量中的值来选择行

vc <- c('a', 'c')
Run Code Online (Sandbox Code Playgroud)

所以我试过了

dt[dt$fct == vc, ]
Run Code Online (Sandbox Code Playgroud)

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

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

joh*_*nes 105

看看?"%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
Run Code Online (Sandbox Code Playgroud)

你也可以使用?is.element:

dt[is.element(dt$fct, vc),]
Run Code Online (Sandbox Code Playgroud)


And*_*nes 22

与上述类似,使用filterfrom dplyr:

filter(df, fct %in% vc)
Run Code Online (Sandbox Code Playgroud)


Jaa*_*aap 9

另一种选择是使用键控data.table:

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

这导致:

   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
Run Code Online (Sandbox Code Playgroud)

这是做什么的:

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

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

可以在插图密钥和基于快速二进制搜索的子集中找到关于密钥和子集的概念的更详细解释.

@Frank在评论中提出的另一种选择:

setDT(dt)[J(vc), on=.(fct)]
Run Code Online (Sandbox Code Playgroud)

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

setDT(dt, key = 'fct')[J(vc), nomatch = 0]
Run Code Online (Sandbox Code Playgroud)

要么:

setDT(dt)[J(vc), on=.(fct), nomatch = 0]
Run Code Online (Sandbox Code Playgroud)

  • @user2017023,是的,例如 `setDT(dt)[!(vc), on=.(fct)]` (2认同)