2016-08-16 43 views
1

我有一个数据集,则类似于以下内容:R:如何与两个条件选择行(买这两种产品)

ID = c(1,2,3,4,1,2,3) 
Product = c("a", "b", "c", "a","b","a","a") 
Quantity = c(1,1,1,1,1,1,1) 
df = data.frame(ID, Product, Quantity) 

# ID Product Quantity 
#1 1  a  1 
#2 2  b  1 
#3 3  c  1 
#4 4  a  1 
#5 1  b  1 
#6 2  a  1 
#7 3  a  1 

我想选择谁购买这两种产品和产品B的人。在上面的例子中,我想要的结果是:

ID Product Quantity 
1 a  1 
2 b  1 
1 b  1 
2 a  1 

我不记得一个功能,为我做这个。我能想到的是通过循环,但我希望找到更简洁的解决方案。

回答

4

你可以做dplyr

library(dplyr) 

df %>% 
    filter(Product %in% c('a','b')) %>% # Grab only desired products 
    group_by(ID)     %>% # For each ID... 
    filter(n() > 1)     %>% # Only grab IDs where the count >1 
    ungroup        # Remove grouping. 

## # A tibble: 4 x 3 
##  ID Product Quantity 
## <dbl> <fctr> <dbl> 
## 1  1  a  1 
## 2  2  b  1 
## 3  1  b  1 
## 4  2  a  1 

编辑以下

这里有一个稍微更简洁dplyr版本使用any(类似于Psidom如何使用它在data.table溶液):

df %>% 
    group_by(ID) %>% 
    filter(all(c('a','b') %in% as.character(Product))) %>% 
    ungroup 
6

With ave

df[ 
with(df, ave(as.character(Product), ID, FUN=function(x) all(c("a","b") %in% x)))=="TRUE", 
] 
# ID Product Quantity 
#1 1  a  1 
#2 2  b  1 
#5 1  b  1 
#6 2  a  1 
+0

@ZheyuanLi一种选择 - 我从来没有改变脚本中正式宣布他们之外的默认值。基于假设他们的设置与我的设置相同,破坏与他人共享代码的潜力太大。 – thelatemail

+0

为什么'==“TRUE”'? – Gregor

+0

@Gregor - 因为'ave'将'FUN ='的逻辑结果转换回''character',这意味着我不能与'TRUE'进行比较,而是''TRUE' – thelatemail

3

使用data.table另一种选择:

library(data.table) 
setDT(df)[, .SD[all(c("a", "b") %in% Product)], ID] 

# ID Product Quantity 
#1: 1  a  1 
#2: 1  b  1 
#3: 2  b  1 
#4: 2  a  1 
1

下面是使用data.table

library(data.table) 
setDT(df, key = "Product")[c("a", "b")][, if(uniqueN(Product)==2) .SD , ID] 
# ID Product Quantity 
#1: 1  a  1 
#2: 1  b  1 
#3: 2  a  1 
#4: 2  b  1