Pandas:如何将 MultiIndex DataFrame 与单个索引 DataFrame 连接,以及自定义排序

Posted

技术标签:

【中文标题】Pandas:如何将 MultiIndex DataFrame 与单个索引 DataFrame 连接,以及自定义排序【英文标题】:Pandas: how to concatenate a MultiIndex DataFrame with a single index DataFrame, and custom ordering 【发布时间】:2018-05-13 16:30:47 【问题描述】:

我有一个 MultiIndex pandas DataFrame df_multi 像:

import pandas as pd

df_multi = pd.DataFrame([['A', 'A1', 0,234,2002],['A', 'A1', 1,324,2550],
['A', 'A1', 2,345,3207],['A', 'A1', 3,458,4560],['A', 'A2', 0,569,1980],
['A', 'A2', 1,657,2314],['A', 'A2', 2,768,4568],['A', 'A2', 3,823,5761]], 
columns=['Product','Scenario','Time','Quantity','Price']).set_index(
['Product', 'Scenario'])

和一个单一的索引 DataFrame df_single 类似:

df_single = pd.DataFrame([['A', -3,100],['A', -2,100], ['A', -1,100]],
columns=['Product','Time','Quantity']).set_index(['Product'])

对于df_multi 的第一级索引中的每个“产品”,以及第二级中的每个“场景”,我想附加/连接df_single 中的行,其中包含一些负的“时间”要在 df_multi 中的正“时间”值之前附加的值开始。

我还希望生成的 DataFrame 首先由 ['Product','Scenario'] 进行多重索引(就像df_multi),然后是按“时间”值升序排列的行。换句话说,期望的结果是:

df_result = pd.DataFrame([['A', 'A1', -3,100,'NaN'],['A', 'A1', -2,100,'NaN'],
['A', 'A1', -1,100,'NaN'],['A', 'A1', 0,234,2002],['A', 'A1', 1,324,2550],
['A', 'A1', 2,345,3207],['A', 'A1', 3,458,4560],['A','A2', -3,100,'NaN'],
['A', 'A2', -2,100,'NaN'],['A', 'A2', -1,100,'NaN'],['A', 'A2', 0,569,1980],
['A', 'A2', 1,657,2314],['A', 'A2', 2,768,4568],['A', 'A2', 3,823,5761]],
columns=['Product','Scenario','Time','Quantity','Price']).set_index(
['Product', 'Scenario'])

编辑:

df_single 没有“场景”值,这可能会造成混淆。只要 'Product' 匹配,df_single 的相同行将被附加到 df_multi 中的每个场景,它们只是免费“继承”场景值。 我正在使用的实际 DataFrame 相当大(每个产品几千个“产品”,几千个“场景”,每个场景几百个“时间”步骤,加上我没有写在例如),所以我需要以一种完全自动化(希望是快速)的方式来执行此操作。

我尝试使用所有joinconcatmerge 来实现这一点,但我没有成功。实现预期结果的最佳方法是什么?

【问题讨论】:

df_single中没有Scenario。我们是否为 df_multi 中的每个不同场景平均分割 df_single's 产品行?我们是否保证行将始终像发布的 3 和 3 示例一样均匀分布? 确实在 df_single 中没有场景,因为 df_single 中表示的新行对于每个场景都是相同的。只要“产品”匹配 en df_multi 和 df_single,我想将 df_single 的相同切片附加到 df_multi 中的每个场景,并自动为其分配“当前”场景值。 您知道 df_single 中有重复项吗?如果它们是合法记录,为什么不将所有 6 都附加到 A1A2 场景而不是 3 和 3? 对重复的内容道歉,我在那里遇到了一些复制粘贴问题。我现在已经删除了它们。有没有办法将代码直接在 *** 中生成的 DataFrame 可视化? (如果你想让人们在更大的数据帧上测试它的可扩展性,请将数据帧 sn-ps 编辑为长度为 10**N 行的种子随机数据。额外的列无关紧要很多,忽略它们。) 【参考方案1】:

考虑将索引重置为 merge 的列,然后是 groupby 聚合仅返回每个组一次并避免重复。之后,运行串联,concat,然后进行列排序并设置多索引。

# MERGE AND AGGREGATION
df_temp = df_multi.reset_index().merge(df_single.reset_index(), on='Product', suffixes=['','_'])\
                                .groupby(['Product', 'Scenario', 'Time_'])['Quantity_'].max()\
                                .reset_index().rename(columns='Time_':'Time','Quantity_':'Quantity')

# ROW BIND CONCATENATION
df_final = pd.concat([df_multi.reset_index(), df_temp])\
                    .sort_values(['Product','Scenario', 'Time'])\
                    .set_index(['Product', 'Scenario'])[['Time', 'Quantity', 'Price']]
print(df_final)
#                   Time  Quantity   Price
# Product Scenario                        
# A       A1          -3       100     NaN
#         A1          -2       100     NaN
#         A1          -1       100     NaN
#         A1           0       234  2002.0
#         A1           1       324  2550.0
#         A1           2       345  3207.0
#         A1           3       458  4560.0
#         A2          -3       100     NaN
#         A2          -2       100     NaN
#         A2          -1       100     NaN
#         A2           0       569  1980.0
#         A2           1       657  2314.0
#         A2           2       768  4568.0
#         A2           3       823  5761.0

【讨论】:

它有效,谢谢!我对速度/可扩展性很好奇。我将在我使用的真实数据上对其进行测试,以了解它在大型数据帧上的表现。

以上是关于Pandas:如何将 MultiIndex DataFrame 与单个索引 DataFrame 连接,以及自定义排序的主要内容,如果未能解决你的问题,请参考以下文章

Pandas:如何将 MultiIndex DataFrame 与单个索引 DataFrame 连接,以及自定义排序

如何更新 MultiIndex pandas DataFrame 的子集

将级别附加到 pandas MultiIndex

将 MultiIndex Pandas 数据帧乘以来自另一个数据帧的多个标量

如何在Python Pandas中将MultiIndex Dataframes与权重合并?

Pandas 可以将 Excel 组结构读入 Multiindex 吗?