循环遍历df字典以便在Pandas中合并df。

5
我有一个包含数据框的字典,如下所示:
A = pd.DataFrame([[2, 1], [2, 1], [2, 1]], columns=['A', 'B'], index = [1, 2, 3])
B = pd.DataFrame([[1, 1], [2, 2], [3, 3]], columns=['A', 'B'], index = [1, 2, 3])
C = pd.DataFrame([[1, 2], [1, 2], [1, 2]], columns=['A', 'B'], index = [1, 2, 3])

df_all = {'df1': A, 'df2': B, 'df3': C}

我希望您能够使用for循环迭代,按照它们的索引将它们“inner”合并。这相当于执行以下操作:
df4 = pd.merge(A, B, left_index=True, right_index=True, how='inner')
df5 = pd.merge(df4, C, left_index=True, right_index=True, how='inner')

结果将会如下所示。
   A_x  B_x  A_y  B_y  A  B
1    2    1    1    1  1  2
2    2    1    2    2  1  2
3    2    1    3    3  1  2

我尝试了一些傻瓜式的操作,例如:

for key, value in df_all.iteritems():
    df = pd.merge(value, value, left_index=True, right_index=True, how='inner')

但是这给了我一个荒谬的结果。
感谢您的帮助。

尝试使用pd.merge(A, A, ...),你就会明白为什么你的结果不起作用了。 - chrisaycock
@chrisaycock 我知道为什么它们不起作用。问题是我不知道如何让它们起作用。有什么线索吗? - hernanavella
2个回答

7
import pandas as pd
import functools

A = pd.DataFrame([[2, 1], [2, 1], [2, 1]], columns=['A', 'B'], index = [1, 2, 3])
B = pd.DataFrame([[1, 1], [2, 2], [3, 3]], columns=['A', 'B'], index = [1, 2, 3])
C = pd.DataFrame([[1, 2], [1, 2], [1, 2]], columns=['A', 'B'], index = [1, 2, 3])

df_all = {'df1': A, 'df2': B, 'df3': C}
merge = functools.partial(pd.merge, left_index=True, right_index=True, how='inner')
df = functools.reduce(merge, df_all.values())
print(df)

收益
   A_x  B_x  A_y  B_y  A  B
1    2    1    1    2  1  1
2    2    1    1    2  2  2
3    2    1    1    2  3  3

请注意,df_all.values() 返回字典中的值,并未按照特定顺序排列。如果您想要特定的顺序,您需要根据键进行排序...
或者,您可以使用 pd.concat 创建带有分层列的 DataFrame:
df = pd.concat(df_all, axis=1).dropna(axis=0)
print(df)

产量
   df1     df2     df3   
     A  B    A  B    A  B
1    2  1    1  1    1  2
2    2  1    2  2    1  2
3    2  1    3  3    1  2

(注意:在这里使用pd.concat是有风险的——我假设数据框中没有NaN值,但可能具有不同的索引。然后使用dropna生成内连接。)

df具有不同的索引。concat选项是一个不错的替代方案。谢谢。 - hernanavella
当然,df_all.values()是一个列表(或可迭代对象),所以如果你愿意,你可以在这里提供一个不同的列表。 - unutbu
最后一个问题。是否有可能将分层的df转换为普通的df...就像去掉df1..df2的额外级别一样? - hernanavella
或者降低一个级别,df.columns = df.columns.droplevel(0) - unutbu
我确信这个操作有一些参数可供选择。 - Andy Hayden
显示剩余3条评论

2

concat可以帮您解决问题:

In [11]: pd.concat([A, B, C], axis=1, keys=['df1', 'df2', 'df3'])
Out[11]:
   df1     df2     df3
     A  B    A  B    A  B
1    2  1    1  1    1  2
2    2  1    2  2    1  2
3    2  1    3  3    1  2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接