在组内联合非集迭代的有效方法

时间:2016-11-23 22:16:10

标签: python pandas group-by

我有df

df = pd.DataFrame(dict(
        A=['b', 'a', 'b', 'c', 'a', 'c', 'a', 'c', 'a', 'a'],
        B=[[0, 2, 3, 1],
           [9, 6, 7, 2],
           [6, 0, 1, 4],
           [9, 2, 5, 1],
           [5, 1, 4, 8],
           [8, 5, 6, 6],
           [0, 9, 0, 0],
           [2, 6, 1, 8],
           [7, 3, 2, 6],
           [8, 7, 1, 9]]
        ))

我希望按'A'进行分组,然后联合'B'

中的所有列表

df.groupby('A').B.union()df.groupby('A').B.apply(set.union)都不起作用。

我希望结果是

A
a    {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
b                {0, 1, 2, 3, 4, 6}
c                {1, 2, 5, 6, 8, 9}
Name: B, dtype: object

3 个答案:

答案 0 :(得分:5)

问题是你需要在应用联合之前先将它们作为集投射。一种解决方案是使用sum连接组,然后使用map转换为设置

In [28]: df.groupby('A').B.sum().map(set)
Out[28]:
A
a    {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
b                {0, 1, 2, 3, 4, 6}
c                {1, 2, 5, 6, 8, 9}
dtype: object

答案 1 :(得分:2)

maxymoo的答案很好,但由于它首先将所有列表添加到一起,因此可能会不必要地占用大量内存(特别是如果有大量重复内容的话)。

相反,您应该首先将列B转换为集合,之后您可以更有效地减少到单个集合。像这样:

df['B'] = df['B'].map(set)

   A             B
0  b  {0, 1, 2, 3}
1  a  {9, 2, 6, 7}
2  b  {0, 1, 4, 6}
3  c  {9, 2, 5, 1}
4  a  {8, 1, 4, 5}
5  c     {8, 5, 6}
6  a        {0, 9}
7  c  {8, 1, 2, 6}
8  a  {2, 3, 6, 7}
9  a  {8, 1, 9, 7}

df.groupby('A').B.apply(lambda x: reduce(set.union, x))

A
a    {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
b                {0, 1, 2, 3, 4, 6}
c                {1, 2, 5, 6, 8, 9}
Name: B, dtype: object

或者,作为一个单行,如maxymoo所指出的那样:

df.groupby('A').B.apply(lambda x : reduce(set.union, x.map(set)))

答案 2 :(得分:1)

我将使用函数来应用

def f(x):
    # grabbing first one so I can
    # make a set out of it
    first, *rest = x.values.tolist()
    # union won't work unless it's on
    # a set, it doesn't care about the rest
    return set(first).union(*rest)

df.groupby('A').B.apply(f)

A
a    {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
b                {0, 1, 2, 3, 4, 6}
c                {1, 2, 5, 6, 8, 9}
Name: B, dtype: object