获取 Pandas 交叉表中的每个元素

Getting each element in Pandas crosstab

我有下面给出的数据集:

a,b,c
1,1,1
1,1,1
1,1,2
2,1,2
2,1,1
2,2,1

我用 pandas 创建了交叉表:

 cross_tab = pd.crosstab(index=a, columns=[b, c], rownames=['a'], colnames=['b', 'c'])

我的交叉表作为输出给出:

b        1     2
c        1  2  1
a        
1        2  1  0
2        1  1  1

我想针对给定的每个 a、b 和 c 值迭代此交叉表。如何获取 cross_tab[a=1][b=1, c=1] 之类的值?谢谢。

您可以使用 slicers:

a,b,c = 1,1,1
idx = pd.IndexSlice
print (cross_tab.loc[a, idx[b,c]])
2

您还可以通过 DataFrame.unstack, reorder_levels and then use loc:

重塑 df
a = cross_tab.unstack().reorder_levels(('a','b','c'))
print (a)
a  b  c
1  1  1    2
2  1  1    1
1  1  2    1
2  1  2    1
1  2  1    0
2  2  1    1
dtype: int64

print (a.loc[1,1,1])
2

您正在寻找df2.xxx.get_level_values

In [777]: cross_tab.loc[cross_tab.index.get_level_values('a') == 1,\
                        (cross_tab.columns.get_level_values('b') == 1)\
                      & (cross_tab.columns.get_level_values('c') == 1)]
Out[777]: 
b  1
c  1
a   
1  2

另一种考虑方式,尽管会损失一点可读性,可能是简单地使用 .loc 来导航 pandas.crosstab 生成的层次索引。下面的例子说明了这一点:

import pandas as pd
import numpy as np

np.random.seed(1234)

df = pd.DataFrame(
    {
        "a": np.random.choice([1, 2], 5, replace=True),
        "b": np.random.choice([11, 12, 13], 5, replace=True),
        "c": np.random.choice([21, 22, 23], 5, replace=True),
    }
)
df

输出

    a   b   c
0   2   11  23
1   2   11  23
2   1   12  23
3   2   12  21
4   1   12  21

crosstab 输出为:

cross_tab = pd.crosstab(
    index=df.a, columns=[df.b, df.c], rownames=["a"], colnames=["b", "c"]
)
cross_tab

b   11  12
c   23  21  23
a           
1   0   1   1
2   2   1   0

现在假设您想在 a==2b==11c==23 时访问值,然后只需执行

cross_tab.loc[2].loc[11].loc[23]

2

为什么这行得通? .loc 允许通过索引 标签 到 select。在 crosstab 输出的数据框中,我们的 以前的列值现在变成了索引标签 。因此,对于我们所做的每个 .loc selection,它都会给出与该索引标签对应的数据帧切片。让我们逐步导航 cross_tab.loc[2].loc[11].loc[23]

cross_tab.loc[2]

产量:

b   c 
11  23    2
12  21    1
    23    0
Name: 2, dtype: int64

下一个:

cross_tab.loc[2].loc[11]

产量:

c
23    2
Name: 2, dtype: int64

终于有了

cross_tab.loc[2].loc[11].loc[23]

产生:

2

为什么我说这会降低可读性呢?因为要理解这个 selection 你必须知道交叉表是如何创建的,即行是 a 而列是 [b, c] 的顺序。你必须知道这一点才能解释 cross_tab.loc[2].loc[11].loc[23] 会做什么。但我发现这通常是一个很好的权衡。