透视具有分层索引的表

时间:2013-09-12 16:09:58

标签: python pandas

这是一个简单的问题,但由于某种原因,我无法找到一个简单的解决方案。

我有一个分层索引的系列,例如:

s = pd.Series(data=randint(0, 3, 45),
              index=pd.MultiIndex.from_tuples(list(itertools.product('pqr',[0,1,2],'abcde')),
              names=['Index1', 'Index2', 'Index3']), name='P')

s = s.map({0:'A', 1:'B', 2:'C'})

所以它看起来像

Index1  Index2  Index3
p       0       a         A
                b         A
                c         C
                d         B
                e         C
        1       a         B
                b         C
                c         C
                d         B
                e         B
q       0       a         B
                b         C
                c         C
                d         C
                e         C
        1       a         A
                b         A
                c         B
                d         C
                e         A

我想按值进行频率计数,以使输出看起来像

Index1  Index2  P
p       0       A         2
                B         1
                C         2
        1       A         0
                B         3
                C         2
q       0       A         0
                B         1
                C         4
        1       A         3
                B         1
                C         1

1 个答案:

答案 0 :(得分:3)

您可以将value_counts应用于系列组:

In [11]: s.groupby(level=[0, 1]).value_counts()  # equiv .apply(pd.value_counts)
Out[11]: 
Index1  Index2   
p       0       C    2
                A    2
                B    1
        1       B    3
                A    2
        2       A    3
                B    1
                C    1
q       0       A    3
                B    1
                C    1
        1       B    2
                C    2
                A    1
        2       C    3
                B    1
                A    1
r       0       A    3
                B    1
                C    1
        1       B    3
                C    2
        2       B    3
                C    1
                A    1
dtype: int64

如果你想包含0(上面没有)你可以使用cross_tab

In [21]: ct = pd.crosstab(rows=[s.index.get_level_values(0), s.index.get_level_values(1)],
                          cols=s.values,
                          aggfunc=len,
                          rownames=s.index.names[:2],
                          colnames=s.index.names[2:3])

In [22]: ct
Out[22]: 
Index3         A  B  C
Index1 Index2         
p      0       2  1  2
       1       2  3  0
       2       3  1  1
q      0       3  1  1
       1       1  2  2
       2       1  1  3
r      0       3  1  1
       1       0  3  2
       2       1  3  1

In [23]: ct.stack()
Out[23]: 
Index1  Index2  Index3
p       0       A         2
                B         1
                C         2
        1       A         2
                B         3
                C         0
        2       A         3
                B         1
                C         1
q       0       A         3
                B         1
                C         1
        1       A         1
                B         2
                C         2
        2       A         1
                B         1
                C         3
r       0       A         3
                B         1
                C         1
        1       A         0
                B         3
                C         2
        2       A         1
                B         3
                C         1
dtype: int64

哪个可能会稍快......