Python Pandas - 重复字典以适应 MultiIndex Dataframe

Python Pandas - Repeat dict to fit in MultiIndex Dataframe

提问人:Aster 提问时间:11/11/2023 更新时间:11/11/2023 访问量:42

问:

我有想要使用的 MultiIndex Dataframe 的结构(灵感来自文档)。我想用一个字典在每个级别上实例化它。

MultiIndex DataFrame 常规结构:

import pandas as pd

def mklbl(prefix, n):
    return ["%s%s" % (prefix, i) for i in range(n)]

miindex = pd.MultiIndex.from_product(
    [mklbl("X", 2), mklbl("Y", 2), mklbl("Z", 2)]
)

columns = ['A', 'B', 'C']

dfmi = (
    pd.DataFrame(
        # Code below from the documentation. To replace??
        # np.arange(len(miindex) * len(columns)).reshape(
        #   (len(miindex), len(columns))
        ),
        index=miindex,
        columns=columns,
    )
    .sort_index()
    .sort_index(axis=1)
)

我希望以某种方式将上面注释的代码替换为以下字典的几次重复,这些字典适合 MultiIndex,

my_dict = {'A': [False, False, True, True], 
           'B': [False, True, False, True], 
           'C': [0, 0, 0, 0]}

这样我最终的结果:

               A       B   C
X0 Y0 Z0   False   False   0
           False   True    0
           True    False   0
           True    True    0
      Z1   False   False   0
           False   True    0
           True    False   0
           True    True    0
   Y1 Z0   False   False   0
           False   True    0
           True    False   0
           True    True    0
      Z1   False   False   0
           False   True    0
           True    False   0
           True    True    0
X1 Y0 Z0   False   False   0
           False   True    0
           True    False   0
           True    True    0
      Z1   False   False   0
           False   True    0
           True    False   0
           True    True    0
   Y1 Z0   False   False   0
           False   True    0
           True    False   0
           True    True    0
      Z1   False   False   0
           False   True    0
           True    False   0
           True    True    0

我试着玩,但没有成功。可能吗?pd.concat()

python-3.x 熊猫 字典 多索引

评论


答:

2赞 mozway 11/11/2023 #1

您可以结合使用 concatitertools.product

from itertools import product

prod = product(mklbl("X", 2), mklbl("Y", 2), mklbl("Z", 2))

tmp = pd.DataFrame(my_dict)

out = pd.concat({p: tmp for p in prod})

或者,如果您已经有 ,请使用交叉合并dfmi

out = (dfmi[[]]
 .reset_index()
 .merge(pd.DataFrame(my_dict), how='cross')
)

out = (out
 .set_index(list(out)[:dfmi.index.nlevels])
 .rename_axis(index=[None]*dfmi.index.nlevels)
)

输出:

                A      B  C
X0 Y0 Z0 0  False  False  0
         1  False   True  0
         2   True  False  0
         3   True   True  0
      Z1 0  False  False  0
         1  False   True  0
         2   True  False  0
         3   True   True  0
   Y1 Z0 0  False  False  0
         1  False   True  0
         2   True  False  0
         3   True   True  0
      Z1 0  False  False  0
         1  False   True  0
         2   True  False  0
         3   True   True  0
X1 Y0 Z0 0  False  False  0
         1  False   True  0
         2   True  False  0
         3   True   True  0
      Z1 0  False  False  0
         1  False   True  0
         2   True  False  0
         3   True   True  0
   Y1 Z0 0  False  False  0
         1  False   True  0
         2   True  False  0
         3   True   True  0
      Z1 0  False  False  0
         1  False   True  0
         2   True  False  0
         3   True   True  0
2赞 Eelco van Vliet 11/11/2023 #2

为了用字典填充你的数据帧,你应该再添加一个级别,你的数据帧列的长度:

miindex = pd.MultiIndex.from_product(
    [mklbl("X", 2), mklbl("Y", 2), mklbl("Z", 2), mklbl("", 4)]
)

然后,您可以通过遍历索引来添加字典,如下所示:

data_df = pd.DataFrame(index=miindex, columns=columns)
for index_x, data_x in data_df.groupby(level=0, ):
    for index_y, data_y in data_x.loc[index_x].groupby(level=0):
        for index_z, data_z in data_y.loc[index_y].groupby(level=0):
            for col_name, col_values in imy_dict.items():
                data_df.loc[(index_x, index_y, index_z), col_name] = col_values

结果如下所示:

print(data_df)

                A      B  C
X0 Y0 Z0 0  False  False  0
         1  False   True  0
         2   True  False  0
         3   True   True  0
      Z1 0  False  False  0
         1  False   True  0
         2   True  False  0
         3   True   True  0
   Y1 Z0 0  False  False  0
         1  False   True  0
         2   True  False  0
         3   True   True  0
      Z1 0  False  False  0
         1  False   True  0
         2   True  False  0
         3   True   True  0
X1 Y0 Z0 0  False  False  0
         1  False   True  0
         2   True  False  0
         3   True   True  0
      Z1 0  False  False  0
         1  False   True  0
         2   True  False  0
         3   True   True  0
   Y1 Z0 0  False  False  0
         1  False   True  0
         2   True  False  0
         3   True   True  0
      Z1 0  False  False  0
         1  False   True  0
         2   True  False  0
         3   True   True  0