获取 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==2
、b==11
和 c==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]
会做什么。但我发现这通常是一个很好的权衡。
我有下面给出的数据集:
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==2
、b==11
和 c==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]
会做什么。但我发现这通常是一个很好的权衡。