首页 文章

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

提问于
浏览
46

我有类似这样的数据:

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 回答

  • 7

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

    与上面类似,使用 filter 来自 dplyr

    filter(df, fct %in% vc)
    
  • 16

    另一个选择是使用键控 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 列设置为键 .

    • 接下来,您可以使用 [J(vc)]vc 向量进行子集化 .

    注意:当键是因子/字符变量时,您也可以使用 setDT(dt, key = 'fct')[vc] 但是当 vc 是数字向量时,这将不起作用 . 当 vc 是数字向量且未包装在 J().() 中时, 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]
    

相关问题