我的数据类似于:
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
?
答案 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.table
(data.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]