根据R中单行中的多个必需值匹配/查找行

时间:2016-03-10 17:30:18

标签: r dataframe

这一定是重复但我无法找到它。所以这里。

我有一个包含两列的data.frame。一个包含一个组,另一个包含一个标准。一个组可以包含许多不同的标准,但每行只有一个。我想识别包含三个特定标准的组(但是会显示在不同的行上。在​​我的情况下,我想要识别包含标准的所有组"我"," E" ," C"。组可以包含这些和其他几个字母的任何数字和组合。

test <- data.frame(grp=c(1,1,2,2,2,3,3,3,4,4,4,4,4),val=c("C","I","E","I","C","E","I","A","C","I","E","E","A"))

> test
  grp val
1    1   C
2    1   I
3    2   E
4    2   I
5    2   C
6    3   E
7    3   I
8    3   A
9    4   C
10   4   I
11   4   E
12   4   E
13   4   A

在上面的例子中,我想识别grp 2和4,因为每个都包含字母E,I和C.

谢谢!

2 个答案:

答案 0 :(得分:2)

library(data.table)

test <- data.frame(grp=c(1,1,2,2,2,3,3,3,4,4,4,4,4),val=c("C","I","E","I","C","E","I","A","C","I","E","E","A"))

setDT(test)      # convert the data.frame into a data.table
group.counts <- dcast(test, grp ~ val)  # count number of same values per group and create one column per val with the count in the cell
group.counts[I>0 & E>0 & C>0,]          # now filtering is easy

结果:

   grp A C E I
1:   2 0 1 1 1
2:   4 1 1 2 1

除了返回组号,您还可以将结果组号与原始数据“连接”起来,以显示匹配的每个组的“原始”数据行:

test[group.counts[I>0 & E>0 & C>0,], .SD, on="grp" ]

这表明:

   grp val
1:   2   E
2:   2   I
3:   2   C
4:   4   C
5:   4   I
6:   4   E
7:   4   E
8:   4   A

PS:只是为了更容易理解解决方案:所有组的计数是:

> group.counts
   grp A C E I
1:   1 0 1 0 1
2:   2 0 1 1 1
3:   3 1 0 1 1
4:   4 1 1 2 1

答案 1 :(得分:2)

这是一个dplyr解决方案。 %in%被向量化,因此c("E", "I", "C") %in% val返回长度为3的逻辑向量。对于目标组,将该向量传递给all()会返回TRUE。这是我们的过滤器,我们使用group_by()在每个组中运行它。

library(dplyr)
test %>% 
  group_by(grp) %>%
  filter(all(c("E", "I", "C") %in% val))
# Source: local data frame [8 x 2]
# Groups: grp [2]
# 
#     grp    val
#   (dbl) (fctr)
# 1     2      E
# 2     2      I
# 3     2      C
# 4     4      C
# 5     4      I
# 6     4      E
# 7     4      E
# 8     4      A

或者如果这个输出更方便(感谢@Frank),

test %>%
  group_by(grp) %>%
  summarise(matching = all(c("E", "I", "C") %in% val))
# Source: local data frame [4 x 2]
# 
#     grp matching
#   (dbl)    (lgl)
# 1     1    FALSE
# 2     2     TRUE
# 3     3    FALSE
# 4     4     TRUE