用STRING_AGG对几列进行相当于groub的pandas

时间:2018-09-12 15:53:06

标签: python pandas aggregate apply group-concat

因此,有一种方法可以对DataFrame对象进行分组,然后对其余的列,将所有条目放入一个集合(或具有过滤后的唯一值的列表)中。像这样

   Name        Date  Amount   purchase
0  Jack  2016-01-31      10    'apple'
1  Jack  2016-02-29       5        25
2  Jack  2016-02-29       8       'B+'
3  Jill  2016-01-31      10       'D2'
4  Jill  2016-02-29       5         E
4  Jill  2016-02-29       5         E

,然后按前两列分组后输出。

    Name        Date  Amount     purchase
 0  Jack  2016-01-31     [10]     [apple]
 1  Jack  2016-02-29    [5,8]   [25,'B+']
 3  Jill  2016-01-31     [10]      ['D2']
 4  Jill  2016-02-29      [5]       ['E']

所以我可以用df_data = df.groupby(['Name', 'Date'])['Amount'].apply(set)对每一列进行处理,然后将它们连接起来,但是如果列表很长,有没有更短的更优雅的解决方案?

2 个答案:

答案 0 :(得分:1)

您可以使用groupby的聚合功能。另外,您将必须重置索引。

df_data = df.groupby(['Name', 'Date']).aggregate(lambda x: list(x)).reset_index()

答案 1 :(得分:0)

不要这样做

Pandas从未被设计为容纳系列/列中的列表。您可以炮制昂贵的解决方法,但不建议使用这些方法。

不建议连续使用列表的主要原因是,您失去了使用连续内存块中保存的NumPy数组的矢量化功能。您的系列将是object dtype,它代表一系列指针,非常类似于list

当然,对于混合类型,object dtype是不可避免的。但是,这里的效果是由嵌套的指针结构引起的。您将在内存和性能以及访问优化的Pandas方法方面失去好处。


一个更好的选择

您可以聚合为字符串,以便只有一个指针级别:

res = df.groupby(['Name', 'Date'], as_index=False)[['Amount', 'purchase']]\
        .agg(lambda x: ', '.join(map(str, set(x))))

print(res)

   Name        Date Amount  purchase
0  Jack  2016-01-31     10   'apple'
1  Jack  2016-02-29   8, 5  'B+', 25
2  Jill  2016-01-31     10      'D2'
3  Jill  2016-02-29      5         E