【发布时间】:2020-10-28 01:10:07
【问题描述】:
我有一个具有多索引的数据框,其中一个级别的值代表该级别的所有其他值。例如(下面的代码示例):
D
A B C
x a y 0
b y 1
all z 2
这里all 是表示该级别所有其他值的简写,因此数据框实际上表示:
D
A B C
x a y 0
b y 1
a z 2
b z 2
这也是我想要得到的形式。对于在该索引级别中包含all 的每一行,该行在索引级别中的每个其他值都重复。如果它是一列,我可以将每次出现的all 替换为其他值的列表,然后使用DataFrame.explode。
所以我考虑重置该索引级别,将所有出现的 all 替换为其他值的列表,然后将 explode 该列替换为索引:
level_values = sorted(set(df.index.unique('B')) - {'all'})
tmp = df.reset_index('B')
mask = df.index.get_level_values('B') == 'all'
col_index = list(tmp.columns).index('B')
for i in np.argwhere(mask).ravel():
tmp.iat[i, col_index] = level_values
result = tmp.explode('B').set_index('B', append=True)
然而,这似乎效率很低,代码也不是很清楚。现在索引级别的顺序也错误(我的实际数据框有三个以上的索引级别,所以我不能使用swaplevel 重新排序)。
所以我想知道是否有更简洁的方法来分解这些 all 值?
生成示例数据帧的代码:
import numpy as np
import pandas as pd
df = pd.DataFrame(
data=[[0], [1], [2]],
index=pd.MultiIndex.from_arrays(
[['x', 'x', 'x'], ['a', 'b', 'all'], ['y', 'y', 'z']],
names=['A', 'B', 'C']
),
columns=['D']
)
expected = pd.DataFrame(
data=[[0], [1], [2], [2]],
index=pd.MultiIndex.from_arrays(
[['x', 'x', 'x', 'x'], ['a', 'b', 'a', 'b'], ['y', 'y', 'z', 'z']],
names=['A', 'B', 'C']
),
columns=['D']
)
【问题讨论】: