2017-12-03 20 views
5

Tôi có một dataframe gấu trúc df:Làm thế nào tạo ra tất cả các cặp giá trị, từ kết quả của một groupby, trong một dataframe gấu trúc

ID  words 
1  word1 
1  word2 
1  word3 
2  word4 
2  word5 
3  word6 
3  word7 
3  word8 
3  word9 

Tôi muốn tạo ra một dataframe rằng sẽ tạo ra tất cả các cặp của các từ trong mỗi nhóm. Vì vậy, các kết quả cho ở trên sẽ là:

ID  wordA wordB 
1  word1 word2 
1  word1 word3 
1  word2 word3 
2  word4 word5 
3  word6 word7 
3  word6 word8 
3  word6 word9 
3  word7 word8 
3  word7 word9 
3  word8 word9 

Tôi biết rằng tôi có thể sử dụng df.groupby['words'] để có được những lời trong mỗi ID.

Tôi cũng biết rằng tôi có thể sử dụng

iterable = ['word1','word2','word3'] 
list(itertools.combinations(iterable, 2)) 

để có được tất cả các kết hợp cặp càng tốt. Tuy nhiên, tôi là một chút bị mất như là cách tốt nhất để tạo ra một dataframe kết quả như được hiển thị ở trên.

+0

Tôi đã chỉnh sửa tiêu đề để phản ánh tốt hơn vấn đề thực tế yo u đang cố gắng giải quyết. –

+1

không có tiêu đề mới không có gì để làm với những gì tôi muốn ... cảm ơn cho các nỗ lực mặc dù ... – BKS

+0

Có thể trùng lặp: https://stackoverflow.com/questions/43800390/how-to-create-all-combinations- column-wise-for-multiple-variables-in-pandas –

Trả lời

3

sử dụng đơn giản của nó itertools kết hợp bên trong áp dụng và chồng tức

from itertools import combinations 
ndf = df.groupby('ID')['words'].apply(lambda x : list(combinations(x.values,2))) 
          .apply(pd.Series).stack().reset_index(level=0,name='words') 

ID   words 
0 1 (word1, word2) 
1 1 (word1, word3) 
2 1 (word2, word3) 
0 2 (word4, word5) 
0 3 (word6, word7) 
1 3 (word6, word8) 
2 3 (word6, word9) 
3 3 (word7, word8) 
4 3 (word7, word9) 
5 3 (word8, word9) 

Để phù hợp với bạn đầu ra chính xác hơn nữa chúng ta phải làm

sdf = pd.concat([ndf['ID'],ndf['words'].apply(pd.Series)],1).set_axis(['ID','WordsA','WordsB'],1,inplace=False) 

    ID WordsA WordsB 
0 1 word1 word2 
1 1 word1 word3 
2 1 word2 word3 
0 2 word4 word5 
0 3 word6 word7 
1 3 word6 word8 
2 3 word6 word9 
3 3 word7 word8 
4 3 word7 word9 
5 3 word8 word9 

Để chuyển đổi nó thành một dòng chúng tôi có thể làm:

combo = df.groupby('ID')['words'].apply(combinations,2)\ 
        .apply(list).apply(pd.Series)\ 
        .stack().apply(pd.Series)\ 
        .set_axis(['WordsA','WordsB'],1,inplace=False)\ 
        .reset_index(level=0) 
+0

Mặc dù vậy, có vẻ như kết quả sẽ được chia thành hai cột trong OP, đó là một bước khác? Tôi tò mò liệu tất cả điều này kết thúc hiệu quả hơn là chỉ xây dựng một df mới? Sẽ không áp dụng 'chạy như một vòng python ở đây? – roganjosh

+0

Ah, tôi đã viết chậm bình luận đầu tiên của tôi lại: bước tiếp theo :) – roganjosh

+0

Hmmm, có vẻ như có trở lại tốt hơn 'DataFrame' từ' apply';) – jezrael

2

Bạn có thể xác định hàm tùy chỉnh được áp dụng cho từng nhóm. Cả hai đầu vào và đầu ra là một dataframe:

def combine(group): 
    return pd.DataFrame.from_records(itertools.combinations(group.word, 2)) 

df.groupby('ID').apply(combine) 

Kết quả:

  0  1 
ID     
1 0 word1 word2 
    1 word1 word3 
    2 word2 word3 
2 0 word4 word5 
3 0 word6 word7 
    1 word6 word8 
    2 word6 word9 
    3 word7 word8 
    4 word7 word9 
    5 word8 word9 
3

Bạn có thể sử dụng groupby với apply và trở DataFrame, cuối cùng thêm reset_index cho loại bỏ mức độ thứ hai và sau đó cho tạo cột từ chỉ số :

from itertools import combinations 

f = lambda x : pd.DataFrame(list(combinations(x.values,2)), 
          columns=['wordA','wordB']) 
df = (df.groupby('ID')['words'].apply(f) 
           .reset_index(level=1, drop=True) 
           .reset_index()) 
print (df) 
    ID wordA wordB 
0 1 word1 word2 
1 1 word1 word3 
2 1 word2 word3 
3 2 word4 word5 
4 3 word6 word7 
5 3 word6 word8 
6 3 word6 word9 
7 3 word7 word8 
8 3 word7 word9 
9 3 word8 word9 
Các vấn đề liên quan