2016-08-16 51 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