如何在 pandas 的交叉表/pivot_table中使用两种不同的功能?

How to use two different functions within crosstab/pivot_table in pandas?

提问人:HappyPy 提问时间:9/5/2013 最后编辑:cottontailHappyPy 更新时间:11/14/2023 访问量:15784

问:

使用 pandas,是否可以计算包含从两个不同函数计算的值的单个交叉表(或数据透视表)?

import pandas as pd
import numpy as np

c1 = np.repeat(['a','b'], [50, 50], axis=0)
c2 = list('xy'*50)
c3 = np.repeat(['G1','G2'], [50, 50], axis=0)
np.random.shuffle(c3)
c4 = np.repeat([1,2], [50,50],axis=0)
np.random.shuffle(c4)
val = np.random.rand(100)

df = pd.DataFrame({'c1':c1, 'c2':c2, 'c3':c3, 'c4':c4, 'val':val})

frequencyTable = pd.crosstab([df.c1, df.c2], [df.c3, df.c4])
meanVal = pd.crosstab([df.c1, df.c2], [df.c3, df.c4], values=df.val, aggfunc=np.mean)

因此,两个表中的行和列都是相同的,但我真正想要的是一个同时具有频率和平均值的表:

c3           G1                       G2          
c4     1              2              1              2
c1 c2  freq val       freq val       freq val       freq val         
a  x   6    0.624931  5    0.582268  8    0.528231  6    0.362804
   y   7    0.493890  8    0.465741  3    0.613126  7    0.312894
b  x   9    0.488255  5    0.804015  6    0.722640  5    0.369480
   y   6    0.462653  4    0.506791  5    0.583695  10   0.517954
Python 熊猫 合并 数据透视表

评论

0赞 Brian 9/5/2013
你试过用吗?我不知道这是否有效,但我想我以前在某个地方见过它。aggfunc=[func1,func2]
0赞 HappyPy 9/5/2013
@Brian:是的,我刚刚尝试了 joris answer,效果很好!非常感谢!
1赞 Brian 9/5/2013
我应该开始发布我的评论作为答案:-p
0赞 joris 9/5/2013
@Brian是的,对不起,当我看到你的评论时,我已经在输入我的答案了:-)
0赞 Brian 9/5/2013
@joris 不用担心。我的是在黑暗中开枪。你实际上知道你在做什么,哈哈。

答:

15赞 joris 9/5/2013 #1

您可以给出函数列表:

pd.crosstab([df.c1,df.c2], [df.c3,df.c4], values=df.val, aggfunc=[len, np.mean])

如果您想要问题中所示的表格,则必须稍微重新排列级别:

In [42]: table = pd.crosstab([df.c1,df.c2], [df.c3,df.c4], values=df.val, aggfunc=[len, np.mean])

In [43]: table
Out[43]: 
       len                mean                              
c3      G1     G2           G1                  G2          
c4       1  2   1  2         1         2         1         2
c1 c2                                                       
a  x     4  6   8  7  0.303036  0.414474  0.624900  0.425234
   y     5  5   8  7  0.543363  0.480419  0.583499  0.637657
b  x    10  6   4  5  0.400279  0.436929  0.442924  0.287572
   y     6  8   5  6  0.400427  0.623319  0.764506  0.408708

In [44]: table.reorder_levels([1, 2, 0], axis=1).sort_index(axis=1)
Out[44]: 
c3      G1                            G2                         
c4       1              2              1              2          
       len      mean  len      mean  len      mean  len      mean
c1 c2                                                            
a  x     4  0.303036    6  0.414474    8  0.624900    7  0.425234
   y     5  0.543363    5  0.480419    8  0.583499    7  0.637657
b  x    10  0.400279    6  0.436929    4  0.442924    5  0.287572
   y     6  0.400427    8  0.623319    5  0.764506    6  0.408708

评论

0赞 HappyPy 9/6/2013
顺便说一句,在用熔体重塑时,是否有可能制作自己的“len”和“mean”柱?我试过:pd.melt(table.reset_index(), id_vars=['c1','c2']),但我得到了一个名为“NaN”的列,其中“len”和“mean”作为元素。谢谢!
1赞 joris 9/6/2013
你说的“自己的专栏”到底是什么意思?您是否想要一列带有“mean”和一列带有“len”的列,旁边是“c1”、“c2”、“c3”、“c4”列,就像您得到的那样?在这种情况下,您可以直接进行,而不是通过交叉表和熔化。df.groupby(["c1", "c2", "c3", "c4"]).aggregate([len, np.mean]).reset_index()