【问题标题】:Pandas groupby - set of different valuesPandas groupby - 一组不同的值
【发布时间】:2017-11-29 00:05:31
【问题描述】:

我有这个数据框

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)

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

【问题讨论】:

    标签: python pandas dataframe pandas-groupby


    【解决方案1】:

    将 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)
    

    【讨论】:

    • 所以我已经有了类似 'cat2': ['min', 'max', 'nunique'] 的东西,即我已经以多种方式聚合了此列。如何修改您的解决方案以适应这种情况?谢谢
    • 有可能使用自定义函数并通过__name__设置名称,检查上次编辑。
    【解决方案2】:
    x.groupby('cat1')['cat2'].agg(lambda x: set(x))
    

    输出

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

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

    【讨论】:

    • 这里不需要 lambda,因为 set 是可调用的。所以 x.groupby('cat1').agg(set) 做同样的事情,不是吗?
    • 在这种情况下它不起作用,虽然我认为它也可以
    • 请查看我对上述问题的修改。作为更大的聚合字典的一部分,我需要这样做。
    • 此解决方案比基于 uniqueapply 的解决方案快得多。
    【解决方案3】:

    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)
    

    【讨论】:

    • 请查看我对上述问题的修改。作为更大的聚合字典的一部分,我需要这样做。
    【解决方案4】:
    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() 会将这些值作为列拉出。

    【讨论】:

    • 请查看我对上述问题的修改。作为更大的聚合字典的一部分,我需要这样做。
    【解决方案5】:

    或者我们可以在groupby之前过滤数据框

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

    【讨论】:

    • 请查看我对上述问题的修改。作为更大的聚合字典的一部分,我需要这样做。
    猜你喜欢
    • 1970-01-01
    • 2020-05-19
    • 2020-09-08
    • 2017-09-29
    • 2023-01-19
    • 2019-08-03
    • 2018-05-22
    • 1970-01-01
    • 2022-06-13
    相关资源
    最近更新 更多