我有一个像这样的多索引数据框:
import pandas as pd
import numpy as np
df = pd.DataFrame({'ind1': list('aaaaaaaaabbbbbbbbb'),
'ind2': list('cccdddeeecccdddeee'),
'ind3': list(range(3))*6,
'val1': list(range(100, 118)),
'val2': list(range(70, 88))})
df_mult = df.set_index(['ind1', 'ind2', 'ind3'])
val1 val2
ind1 ind2 ind3
a c 0 100 70
1 101 71
2 102 72
d 0 103 73
1 104 74
2 105 75
e 0 106 76
1 107 77
2 108 78
b c 0 109 79
1 110 80
2 111 81
d 0 112 82
1 113 83
2 114 84
e 0 115 85
1 116 86
2 117 87
我现在可以使用.loc
这样的
df_subs = df_mult.loc['a', ['c', 'd'], :]
给出了预期的
val1 val2
ind1 ind2 ind3
a c 0 100 70
1 101 71
2 102 72
d 0 103 73
1 104 74
2 105 75
如果我现在想再次选择df_subs
的子集,例如
df_subs.loc['a', 'c', :]
工作并提供
val1 val2
ind3
0 100 70
1 101 71
2 102 72
然而
df_subs.loc[:, 'c', :]
失败并发出错误
KeyError:'标签[c]不在[栏目]'
为什么这会失败?
修改
最初,我在这篇文章中有两个问题。我把它分成了两个,第二个问题可以找到here。
答案 0 :(得分:2)
使用IndexSlice
:
idx = pd.IndexSlice
df_subs.loc[idx[:, 'c',:],:]
Out[159]:
val1 val2
ind1 ind2 ind3
a c 0 100 70
1 101 71
2 102 72
或者您需要在行或列上的特定切片
df_subs.loc(axis=0)[:, 'c', :]
Out[196]:
val1 val2
ind1 ind2 ind3
a c 0 100 70
1 101 71
2 102 72
.loc[:, 'c', :]
无效的原因:
您应该在.loc说明符中指定所有轴,这意味着索引和列的索引器。有一些模糊的情况,传递的索引器可能被错误解释为索引两个轴,而不是说行的MuliIndex。
答案 1 :(得分:1)
显然,使用.loc
可能会将索引保留为原始格式,直到重置为止。使用.copy()
来避免原始数据框的任何视图仍然存在多索值。
df_subs = df_mult.loc['a', ['c', 'd'], :].copy()
print(df_subs.index)
# MultiIndex(levels=[['a', 'b'], ['c', 'd', 'e'], [0, 1, 2]],
# labels=[[0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1], [0, 1, 2, 0, 1, 2]],
# names=['ind1', 'ind2', 'ind3'])
此外,按值过滤仍保留多索值:
df_subs = df_mult[df_mult['val1'] <= 105]
print(df_subs)
# val1 val2
# ind1 ind2 ind3
# a c 0 100 70
# 1 101 71
# 2 102 72
# d 0 103 73
# 1 104 74
# 2 105 75
print(df_subs.index)
# MultiIndex(levels=[['a', 'b'], ['c', 'd', 'e'], [0, 1, 2]],
# labels=[[0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1], [0, 1, 2, 0, 1, 2]],
# names=['ind1', 'ind2', 'ind3'])
因此,请考虑按照原始作业手动重置索引
df_subs = df_mult.loc['a', ['c', 'd'], :].reset_index()
df_subs = df_subs.set_index(['ind1', 'ind2', 'ind3'])
print(df_subs.index)
# MultiIndex(levels=[['a'], ['c', 'd'], [0, 1, 2]],
# labels=[[0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1], [0, 1, 2, 0, 1, 2]],
# names=['ind1', 'ind2', 'ind3'])
最后,对于最后.loc
作业(#2),至少提供可能需要的第一个索引:
df_subs2 = df_subs.loc['a', 'c', :]
# val1 val2
# ind3
# 0 100 70
# 1 101 71
# 2 102 72