2016-03-10 18 views
5

Đây phải là một bản sao nhưng tôi không thể tìm thấy nó. Vì vậy, ở đây đi.khớp/tìm các hàng dựa trên nhiều giá trị bắt buộc trong một hàng duy nhất trong R

Tôi có một data.frame có hai cột. Một chứa một nhóm và nhóm còn lại chứa một tiêu chí. Một nhóm có thể chứa nhiều tiêu chí khác nhau, nhưng chỉ có một tiêu chí cho mỗi hàng. Tôi muốn xác định các nhóm có chứa ba tiêu chí cụ thể (nhưng điều đó sẽ xuất hiện trên các hàng khác nhau. Trong trường hợp của tôi, tôi muốn xác định tất cả các nhóm có chứa tiêu chí "I", "E", "C". và sự kết hợp của những điều này và nhiều thư khá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 

trong ví dụ trên, tôi muốn xác định grp 2, và 4 vì mỗi người trong các chứa các chữ E, I, và C.

Cảm ơn!

+0

Tôi cho rằng ba duy nhất() các cuộc gọi trong cùng là khá dư thừa và không cần thiết. Tập dữ liệu thực tế của tôi là vài triệu hàng và tôi không chắc liệu nó có nhanh hơn theo cách đó hay không. – Jordan

+0

Vấn đề thú vị! Nó được gọi là ** và/hoặc tiến thoái lưỡng nan truy vấn ** trong bối cảnh cơ sở dữ liệu SQL vì ràng buộc ** và ** yêu cầu ràng buộc trên nhiều hàng (không phải là độ mạnh của SQL). Tôi háo hức được thấy một giải pháp R (tốt hơn)! –

+0

Có bao nhiêu 'val' duy nhất có trong tập dữ liệu của bạn? Tùy thuộc vào số lượng, thông tin đó có thể hướng dẫn một số giải pháp. – JasonAizkalns

Trả lời

2

Đây là giải pháp dplyr. %in% được vector hóa sao cho c("E", "I", "C") %in% val trả về một vectơ lôgic có độ dài ba. Đối với các nhóm mục tiêu, chuyển vectơ đó đến all() trả lại TRUE. Đó là bộ lọc của chúng tôi và chúng tôi chạy nó trong mỗi nhóm bằng cách sử dụng 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 

Hoặc nếu sản lượng này sẽ là handier (nhờ @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 
+2

Đây là một tùy chọn tương tự trong cơ sở: 'tapply (test $ val, test $ grp, function (x) tất cả (myvals% in% x))' where 'myvals = c (" E "," I "," C ") '.Tôi nghĩ rằng 'tóm tắt' là phù hợp hơn với' bộ lọc' ở đây nếu OP chỉ muốn biết các nhóm nào vượt qua tiêu chí. – Frank

+0

Không biết về tất cả(). Tuyệt vời bổ sung từ cả hai bạn. – Jordan

+0

Ý nghĩ hay. Không chắc OP có thực sự muốn các nhóm hay các hàng không. – effel

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 

Kết quả bằng:

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

Thay vì trả lại những con số nhóm duy nhất bạn cũng có thể "tham gia" số nhóm kết quả với dữ liệu gốc để hiển thị "thô" hàng dữ liệu của từng nhóm phù hợp:

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

này show :

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: Chỉ cần để hiểu được những giải pháp dễ dàng hơn: các tính cho tất cả các nhóm là:

> 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 
Các vấn đề liên quan