【问题标题】:Python Pandas : pivot table with aggfunc = count unique distinctPython Pandas:带有 aggfunc = count unique distinct 的数据透视表
【发布时间】:2012-10-03 08:22:35
【问题描述】:

这段代码:

df2 = (
    pd.DataFrame({
        'X' : ['X1', 'X1', 'X1', 'X1'], 
        'Y' : ['Y2', 'Y1', 'Y1', 'Y1'], 
        'Z' : ['Z3', 'Z1', 'Z1', 'Z2']
    })
)
g = df2.groupby('X')
pd.pivot_table(g, values='X', rows='Y', cols='Z', margins=False, aggfunc='count')

返回以下错误:

Traceback (most recent call last): ... 
AttributeError: 'Index' object has no attribute 'index'

如何获得一个数据透视表,其中包含一个 DataFrame 列的唯一值计数,用于其他两列?
是否有 aggfunc 用于唯一计数?我应该使用np.bincount()吗?

注意。我知道pandas.Series.values_counts() 但是我需要一个数据透视表。


编辑:输出应该是:

Z   Z1  Z2  Z3
Y             
Y1   1   1 NaN
Y2 NaN NaN   1

【问题讨论】:

  • 我在Q&A中提供了几个详细的示例和替代方法

标签: python pandas pivot-table


【解决方案1】:

你的意思是这样的吗?

>>> df2.pivot_table(values='X', index='Y', columns='Z', aggfunc=lambda x: len(x.unique()))

Z   Z1  Z2  Z3
Y             
Y1   1   1 NaN
Y2 NaN NaN   1

请注意,使用 len 假设您的 DataFrame 中没有 NAs。否则您可以使用x.value_counts().count()len(x.dropna().unique())

【讨论】:

  • 也可以直接使用 x.nunique() 代替 len(x.unique())
【解决方案2】:
out = df2.pivot_table(values='X', index='Y', columns='Z', aggfunc=['nunique', 'count', lambda x: len(x.unique()), len])

[out]:
             nunique           count           <lambda>            len          
Z       Z1   Z2   Z3    Z1   Z2   Z3       Z1   Z2   Z3   Z1   Z2   Z3
Y                                                                     
Y1     1.0  1.0  NaN   2.0  1.0  NaN      1.0  1.0  NaN  2.0  1.0  NaN
Y2     NaN  NaN  1.0   NaN  NaN  1.0      NaN  NaN  1.0  NaN  NaN  1.0


out = df2.pivot_table(values='X', index='Y', columns='Z', aggfunc='nunique')

[out]:
Z    Z1   Z2   Z3
Y                
Y1  1.0  1.0  NaN
Y2  NaN  NaN  1.0

out = df2.pivot_table(values='X', index='Y', columns='Z', aggfunc=['nunique'])

[out]:
             nunique          
Z       Z1   Z2   Z3
Y                   
Y1     1.0  1.0  NaN
Y2     NaN  NaN  1.0

【讨论】:

    【解决方案3】:

    由于没有一个答案是最新版本的 Pandas,我正在为这个问题编写另一个解决方案:

    import pandas as pd
    
    # Set example
    df2 = (
        pd.DataFrame({
            'X' : ['X1', 'X1', 'X1', 'X1'], 
            'Y' : ['Y2', 'Y1', 'Y1', 'Y1'], 
            'Z' : ['Z3', 'Z1', 'Z1', 'Z2']
        })
    )
    
    # Pivot
    pd.crosstab(index=df2['Y'], columns=df2['Z'], values=df2['X'], aggfunc=pd.Series.nunique)
    

    返回:

    Z   Z1  Z2  Z3
    Y           
    Y1  1.0 1.0 NaN
    Y2  NaN NaN 1.0
    

    【讨论】:

      【解决方案4】:

      aggfunc=pd.Series.nunique 提供不同的计数。完整代码如下:

      df2.pivot_table(values='X', rows='Y', cols='Z', aggfunc=pd.Series.nunique)
      

      此解决方案归功于@hume(请参阅已接受答案下的评论)。在此处添加作为答案以提高可发现性。

      【讨论】:

        【解决方案5】:

        这是对.pivot_table 中的条目进行计数的好方法:

        >>> df2.pivot_table(values='X', index=['Y','Z'], columns='X', aggfunc='count')
        
                X1  X2
        Y   Z       
        Y1  Z1   1   1
            Z2   1  NaN
        Y2  Z3   1  NaN
        

        【讨论】:

        【解决方案6】:

        aggfunc=pd.Series.nunique 只会计算一系列的唯一值 - 在这种情况下,计算列的唯一值。但这并不能完全反映 aggfunc='count'

        的替代品

        对于简单的计数,最好使用aggfunc=pd.Series.count

        【讨论】:

          【解决方案7】:

          为了获得最佳性能,我建议使用DataFrame.drop_duplicates 跟进aggfunc='count'

          其他人认为aggfunc=pd.Series.nunique 可以工作是正确的。但是,如果您拥有的 index 组的数量很大 (>1000),这可能会很慢。

          所以而不是(引用@Javier)

          df2.pivot_table('X', 'Y', 'Z', aggfunc=pd.Series.nunique)
          

          我建议

          df2.drop_duplicates(['X', 'Y', 'Z']).pivot_table('X', 'Y', 'Z', aggfunc='count')
          

          这是可行的,因为它保证每个子组(('Y', 'Z') 的每个组合)都将具有唯一的(非重复的)'X' 值。

          【讨论】:

            【解决方案8】:

            从pandas至少0.16版本开始,它不带参数“rows”

            从 0.23 开始,解决方案是:

            df2.pivot_table(values='X', index='Y', columns='Z', aggfunc=pd.Series.nunique)
            

            返回:

            Z    Z1   Z2   Z3
            Y                
            Y1  1.0  1.0  NaN
            Y2  NaN  NaN  1.0
            

            【讨论】:

              【解决方案9】:

              您可以为X 的每个不同值构建一个数据透视表。在这种情况下,

              for xval, xgroup in g:
                  ptable = pd.pivot_table(xgroup, rows='Y', cols='Z', 
                      margins=False, aggfunc=numpy.size)
              

              将为X 的每个值构建一个数据透视表。您可能希望使用xvalue 索引ptable。使用此代码,我得到 (for X1)

                   X        
              Z   Z1  Z2  Z3
              Y             
              Y1   2   1 NaN
              Y2 NaN NaN   1
              

              【讨论】:

              • 谢谢。但是我没有计算 X 的每个不同值的出现次数,我计算的是 X 中 Y 和 Z 的不同值的数量。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-11-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2023-03-23
              • 2022-11-23
              相关资源
              最近更新 更多