我有一个数据集如下:
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]
之类的值?谢谢。
您正在寻找
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
您可以使用切片机:
a,b,c = 1,1,1
idx = pd.IndexSlice
print (cross_tab.loc[a, idx[b,c]])
2
您还可以通过
df
、
DataFrame.unstack
重塑
reorder_levels
,然后使用 loc
:
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
另一种考虑的方法,尽管会损失一点可读性,可能是简单地使用
.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
允许通过索引标签进行选择。 在crosstab
输出的数据帧中,我们的以前的列值现在变成了索引标签。 因此,对于我们所做的每一个 .loc
选择,它都会给出与该索引标签相对应的数据帧切片。 让我们一步步导航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
为什么我说这会降低可读性呢? 因为要理解此选择,您必须了解交叉表是如何创建的,即行是
a
,列的顺序是 [b, c]
。 您必须知道这一点才能解释 cross_tab.loc[2].loc[11].loc[23]
会做什么。 但我发现这通常是一个很好的权衡。
使用@AlokLal提供的数据:
在当前版本的 Python (3.11.2) 中,
cross_tab.loc[2].loc[11]
不起作用。错误是:ValueError: No axis named 11 for object type Series
一次使用
.loc
功能如下:
>>> print(cross_tab)
b 11 12
c 22 21 22 23
a
1 0 0 1 0
2 2 1 0 1
>>> print(cross_tab.loc[2])
b c
11 22 2
12 21 1
22 0
23 1
Name: 2, dtype: int64
>>> print(cross_tab.loc[2,12])
c
21 1
22 0
23 1
Name: 2, dtype: int64
>>> print(cross_tab.loc[2,12].loc[22])
0