如何在 pandas 数据框中从 groupby 的结果生成所有值对

Posted

技术标签:

【中文标题】如何在 pandas 数据框中从 groupby 的结果生成所有值对【英文标题】:How generate all pairs of values, from the result of a groupby, in a pandas dataframe 【发布时间】:2018-05-17 01:32:17 【问题描述】:

我有一个熊猫数据框df

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

我想生成另一个数据框,该数据框将生成每组中的所有单词对。所以上面的结果是:

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

我知道我可以使用df.groupby['words'] 来获取每个ID 中的单词。

我也知道我可以用

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

获取所有可能的成对组合。但是,对于生成如上所示的结果数据帧的最佳方式,我有点迷茫。

【问题讨论】:

我已经编辑了标题以更好地反映您要解决的实际问题。 不,新标题与我想要的无关...不过感谢您的努力... 可能重复:***.com/questions/43800390/… 是的,我的 itertools 部分是正确的。 :) 我需要弄清楚如何在 groupby 中做到这一点。我正在为每个 ID 做这件事。 【参考方案1】:

它在 apply 和 stack 中简单使用 itertools 组合,即

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)

为了进一步匹配你的精确输出,我们必须做

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

要将其转换为单行,我们可以这样做:

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)

【讨论】:

严格来说,看起来结果应该在 OP 中分成两列,这是另一个步骤吗?我很好奇这一切最终是否比仅仅建立一个新的df更有效? apply 不会在这里作为 python 循环运行吗? 啊,我写第一条评论的速度太慢了:进一步:) 嗯,看来DataFrameapply 返回更好;)【参考方案2】:

您可以将groupbyapply 一起使用并返回DataFrame,最后添加reset_index 用于删除第二级,然后用于从索引创建列:

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

【讨论】:

【参考方案3】:

您可以定义应用于每个组的自定义函数。输入和输出都是一个数据框:

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

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

结果:

          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

【讨论】:

【参考方案4】:

最简单的方法是:

from itertools import combinations
import pandas as pd

df_new = pd.DataFrame(list(combinations(df.words, 2)), columns=['word1', 'word2'])

【讨论】:

以上是关于如何在 pandas 数据框中从 groupby 的结果生成所有值对的主要内容,如果未能解决你的问题,请参考以下文章

如何对一列执行 pandas groupby 操作,但将另一列保留在结果数据框中

Python Pandas 如何将 groupby 操作结果分配回父数据框中的列?

如何在python中使用groupby或pivot在这个pandas数据框中[重复]

将列的名称保留在 groupby 中,并在 pandas 数据框中使用 sum

带有 MultiIndexing 的 Pandas 数据框中的 Groupby

Python pandas:在groupby数据框中插入缺失日期、时间序列的行