将熊猫数据框分组并将多个值收集到集合中

Posted

技术标签:

【中文标题】将熊猫数据框分组并将多个值收集到集合中【英文标题】:Grouping pandas dataframe and collecting multiple values into sets 【发布时间】:2017-11-01 12:00:31 【问题描述】:

假设我有以下数据框df1

     A    B  C   D 
0  foo  one  1  0
1  bar  two  2  1
2  foo  two  3  0
3  bar  two  4  1
4  foo  two  5  0
5  bar  two  6  1
6  foo  one  7  0
7  foo  two  8  1

我想把它变成一个数据框df2,像这样:

A     B            C                 D             
foo  [one,two]  [1,3,5,7,8]          0
bar  [two]          [2,4,6]          1

更准确地说:

A分组,即A列是索引,每行A的值都是唯一的

BC 列包含出现的值的聚合集。对于A = "foo"B"one""two",而对于"bar",它只是"two"

从逻辑上讲,这应该是一个集合,每个出现的值都恰好出现一次。它可能是 Python set,但我也想知道用 pandas 来表示它的最优雅的方式是什么

D 不包含集合,因为对于 fooD 始终为 0,而对于 bar,它始终为 1。如果索引值和列值,则该列不应包含集合。

我预计会有一个像 df1.groupby("A").aggregate_like_this() 这样的单行聚合,但到目前为止我没有找到它。

【问题讨论】:

【参考方案1】:

使用groupby + agg:

f = 'B' : lambda x: np.unique(x).tolist(), 
     'C' : lambda x: np.unique(x).tolist(), 
     'D' : 'first'


df.groupby('A', as_index=False).agg(f).reindex(columns=df.columns)

     A           B                C  D
0  bar       [two]        [2, 4, 6]  1
1  foo  [one, two]  [1, 3, 5, 7, 8]  0 

如果您无法提前确定 A 的哪些值与 D 具有 1:1 的关系,请使用 groupby + nunique 进行检查,然后相应地过滤您的数据集。

x = df.groupby('A').D.nunique().eq(1)
df = df[df.A.isin(x[x].index)]
df

     A    B  C  D
1  bar  two  2  1
3  bar  two  4  1
5  bar  two  6  1

df.groupby('A', as_index=False).agg(f).reindex(columns=df.columns)

     A      B          C  D
0  bar  [two]  [2, 4, 6]  1

【讨论】:

这里我需要事先知道D列与索引值有这种1:1的关系。这意味着我需要为每一列手动测试。有没有办法让 pandas 自动执行此操作? 你写'D': 'first',告诉pandas为列D取第一个值,因为我告诉过你列D有这个属性,只有一个D的值A 的每个值。但如果我们不知道这一点呢? @clstaudt 无论我们是否知道 D 和 A 的关系,它都会盲目地取第一个值。如果没有唯一值,你想做什么? @Wen 这是一个选项,但我认为np.unique 在大型数组上比set 快...而且D 不能成为列表列。 基于他的样本数据,即设置在一组中包含 [0,1] .. :-)

以上是关于将熊猫数据框分组并将多个值收集到集合中的主要内容,如果未能解决你的问题,请参考以下文章

熊猫应用函数将多个值返回到熊猫数据框中的行

熊猫对多个数据框求和

多个熊猫数据框的交集

在熊猫中按多个条件分组[重复]

如何一次将函数应用于熊猫数据框中的多个列

如何分组并将操作聚合到多个列?