Pandas groupby - 一组不同的值

Pandas groupby - set of different values

我有这个数据框

x = pd.DataFrame.from_dict({'cat1':['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C'], 'cat2':['X', 'X', 'Y', 'Y', 'Y', 'Y', 'Z', 'Z']})

  cat1 cat2
0    A    X
1    A    X
2    A    Y
3    B    Y
4    B    Y
5    C    Y
6    C    Z
7    C    Z

我想按 cat1 分组,然后将 cat2 聚合为不同值的集合,例如

  cat1 cat2
0    A    (X, Y)
1    B    (Y,)
2    C    (Y, Z)

这是具有更多列的更大数据框的一部分,每个列都有自己的聚合函数,那么如何将此功能传递给聚合字典?

x.groupby('cat1')['cat2'].agg(lambda x: set(x))

输出

至于评论中建议的简化,看起来以下至少适用于 Python 3.6.5 和 Pandas 0.23.0(但不适用于 Python 3.6.2和 Pandas 0.20.3):

x.groupby('cat1')['cat2'].agg(set)

Groupby 和 unique 为您提供唯一值

x.groupby('cat1').cat2.unique()

A    [X, Y]
B       [Y]
C    [Y, Z]

如果你想在元组中输出,试试

x.groupby('cat1').cat2.unique().apply(tuple)

A    (X, Y)
B      (Y,)
C    (Y, Z)
x.groupby('cat1')['cat2'].unique().reset_index()

# Returns 
  cat1    cat2
0    A  [X, Y]
1    B     [Y]
2    C  [Y, Z]

这首先按 'cat1' 对整个数据帧进行分组,仅选择系列 'cat2',并将每个组缩减为唯一的一组 'cat2' 值。结果将 'cat1' 值放入索引中,因此 reset_index() 会将这些值作为列拉回,如果您需要该格式的话。

或者我们可以在groupby之前过滤dataframe

x.drop_duplicates().groupby('cat1').cat2.apply(tuple)
Out[777]: 
cat1
A    (X, Y)
B      (Y,)
C    (Y, Z)
Name: cat2, dtype: object

将 lambda 函数与 setunique 一起使用,还将输出转换为 tuples:

x = pd.DataFrame.from_dict({'cat1':['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C'], 
                            'cat2':['X', 'X', 'Y', 'Y', 'Y', 'Y', 'Z', 'Z'],
                             'col':range(8)})
print (x)
  cat1 cat2  col
0    A    X    0
1    A    X    1
2    A    Y    2
3    B    Y    3
4    B    Y    4
5    C    Y    5
6    C    Z    6
7    C    Z    7

a = x.groupby('cat1').agg({'cat2': lambda x: tuple(set(x)), 'col':'sum'})
print (a)
        cat2  col
cat1             
A     (Y, X)    3
B       (Y,)    7
C     (Y, Z)   18

或者:

a = x.groupby('cat1').agg({'cat2': lambda x: tuple(x.unique()), 'col':'sum'})
print (a)
        cat2  col
cat1             
A     (X, Y)    3
B       (Y,)    7
C     (Y, Z)   18

编辑:

f = lambda x: tuple(x.unique())
f.__name__ = 'my_name'
a = x.groupby('cat1')['cat2'].agg(['min', 'max', 'nunique', f])
print (a)
     min max  nunique my_name
cat1                         
A      X   Y        2  (X, Y)
B      Y   Y        1    (Y,)
C      Y   Z        2  (Y, Z)

如果只有一个lambda函数或者列名没有问题<lambda>:

a = x.groupby('cat1')['cat2'].agg(['min', 'max', 'nunique', lambda x: tuple(x.unique())])
print (a)
     min max  nunique <lambda>
cat1                          
A      X   Y        2   (X, Y)
B      Y   Y        1     (Y,)
C      Y   Z        2   (Y, Z)