Pandas 连接具有相同行索引的多索引列

Posted

技术标签:

【中文标题】Pandas 连接具有相同行索引的多索引列【英文标题】:Pandas concatenate Multiindex columns with same row index 【发布时间】:2021-02-22 21:28:57 【问题描述】:

我想连接 NumPy 计算的多维输出,其维度与输入的形状匹配(关于行和相应的选定列)。 但它失败了:NotImplementedError: Can only union MultiIndex with MultiIndex or Index of tuples, try mi.to_flat_index().union(other) instead

我不想先将索引变平 - 那么还有其他方法可以让它工作吗?

import pandas as pd
from pandas import Timestamp

df = pd.DataFrame(('metrik_0', Timestamp('2020-01-01 00:00:00')): (1, 1): 2.5393693602911447, (1, 5): 4.316896324314225, (1, 6): 4.271001191238499, (1, 9): 2.8712588011247377, (1, 11): 4.0458495954752545, ('metrik_0', Timestamp('2020-01-01 01:00:00')): (1, 1): 4.02779063729038, (1, 5): 3.3849606155101224, (1, 6): 4.284114856052976, (1, 9): 3.980919941298365, (1, 11): 5.042488191587525, ('metrik_0', Timestamp('2020-01-01 02:00:00')): (1, 1): 2.374592085569529, (1, 5): 3.3405503781564487, (1, 6): 3.4049690284720366, (1, 9): 3.892686173978996, (1, 11): 2.1876998087043127)

def compute_return_columns_to_df(df, colums_to_process,axis=0):
    method = 'compute_result'
    renamed_base_levels = map(lambda x: f'x_method', colums_to_process.get_level_values(0).unique())
    renamed_columns = colums_to_process.set_levels(renamed_base_levels, level=0)

    #####
    # perform calculation in numpy here
    # for the sake of simplicity (and as the actual computation is irrelevant - it is omitted in this minimal example)
    result = df[colums_to_process].values
    #####
    
    result = pd.DataFrame(result, columns=renamed_columns)
    display(result)    
    return pd.concat([df, result], axis=1) # fails with: NotImplementedError: Can only union MultiIndex with MultiIndex or Index of tuples, try mi.to_flat_index().union(other) instead.

# I do not want to flatten the indices first - so is there another way to get it to work?

compute_return_columns_to_df(df[df.columns[0:3]].head(), df.columns[0:2])

【问题讨论】:

你的预期输出是什么? 非常类似于***.com/questions/49277682/… 我只是想将其添加为列。当然可以迭代所有列并添加它 - 但我更愿意一次将所有列添加到源数据框中。 即对于 result.columns 中的 col: df[col] = result[col] return df 当然可以。但需要迭代。 【参考方案1】:

你的代码失败的原因在:

result = df[colums_to_process].values
result = pd.DataFrame(result, columns=renamed_columns)

请注意,结果有:

具有***索引级别的列名重命名为 metrik_0_compute_result(目前还可以), 但行索引是默认的单级索引, 由连续的数字组成。

然后,当您连接 dfresult 时,Pandas 会尝试 在行索引上对齐两个源 DataFrame,但它们不兼容 (df 有一个 MultiIndex,而 result 有一个“普通”索引)。

将这部分代码更改为:

result = df[colums_to_process]
result.columns = renamed_columns

这种方式 result 保持原来的索引和 concat 提出 no 例外。

另外说明:你的函数包含 axis 参数,即 没用过。考虑删除它。

另一种可能的方法

由于 result 有一个默认(单级)索引,您可以将 代码的前一部分按原样,但在加入之前重置 df 中的索引:

return pd.concat([df.reset_index(drop=True), result], axis=1)

这样,两个 DataFrame 具有相同的索引,您可以连接 他们也是。

【讨论】:

这不起作用 - 正如我所说的操作正在 numpy 上工作(= 隐式地删除了 pandas 的原始索引)。所以你是对的 - 但不幸的是,大纲解决方案仅适用于基于 pandas 的简单虚拟示例。

以上是关于Pandas 连接具有相同行索引的多索引列的主要内容,如果未能解决你的问题,请参考以下文章

将 Pandas 数据帧与多索引列和不规则时间戳连接起来

使用多索引列连接两个 pandas 数据框

加入数据框 - 一个具有多索引列,另一个没有

使熊猫具有多索引列的多个数据框并完全连接

具有多索引列的 Pandas groupby

以长格式保存具有不同级别名称的多索引列 Pandas 为 excel 格式