Pandas:合并多个数据帧和控制列名?

时间:2015-12-17 15:54:36

标签: python pandas

我想将九个Pandas数据帧合并到一个数据帧中,在两列上进行连接,控制列名。这可能吗?

我有九个数据集。所有这些都有以下列:

org, name, items,spend

我想将它们加入到包含以下列的单个数据框中:

org, name, items_df1, spend_df1, items_df2, spend_df2, items_df3...

我一直在阅读merging and joining上的文档。我现在可以合并两个数据集,如下所示:

ad = pd.DataFrame.merge(df_presents, df_trees,
                        on=['practice', 'name'],
                        suffixes=['_presents', '_trees'])

这很有效,print list(aggregate_data.columns.values)向我展示了以下列:

[org', u'name', u'spend_presents', u'items_presents', u'spend_trees', u'items_trees'...]

但是如何才能为九列做到这一点? merge似乎一次只能接受两个,如果按顺序执行,我的列名最终会变得非常混乱。

3 个答案:

答案 0 :(得分:6)

您可以使用functools.reduce以迭代方式将pd.merge应用于每个DataFrame:

result = functools.reduce(merge, dfs)

这相当于

result = dfs[0]
for df in dfs[1:]:
    result = merge(result, df)

要传递on=['org', 'name']参数,可以使用functools.partial定义合并函数:

merge = functools.partial(pd.merge, on=['org', 'name'])

由于在suffixes中指定functools.partial参数只允许 一个固定的后缀选择,因为在这里我们需要一个不同的后缀 pd.merge调用,我认为准备DataFrames列最容易 在致电pd.merge之前的姓名:

for i, df in enumerate(dfs, start=1):
    df.rename(columns={col:'{}_df{}'.format(col, i) for col in ('items', 'spend')}, 
              inplace=True)

例如,

import pandas as pd
import numpy as np
import functools
np.random.seed(2015)

N = 50
dfs = [pd.DataFrame(np.random.randint(5, size=(N,4)), 
                    columns=['org', 'name', 'items', 'spend']) for i in range(9)]
for i, df in enumerate(dfs, start=1):
    df.rename(columns={col:'{}_df{}'.format(col, i) for col in ('items', 'spend')}, 
              inplace=True)
merge = functools.partial(pd.merge, on=['org', 'name'])
result = functools.reduce(merge, dfs)
print(result.head())

产量

   org  name  items_df1  spend_df1  items_df2  spend_df2  items_df3  \
0    2     4          4          2          3          0          1   
1    2     4          4          2          3          0          1   
2    2     4          4          2          3          0          1   
3    2     4          4          2          3          0          1   
4    2     4          4          2          3          0          1   

   spend_df3  items_df4  spend_df4  items_df5  spend_df5  items_df6  \
0          3          1          0          1          0          4   
1          3          1          0          1          0          4   
2          3          1          0          1          0          4   
3          3          1          0          1          0          4   
4          3          1          0          1          0          4   

   spend_df6  items_df7  spend_df7  items_df8  spend_df8  items_df9  spend_df9  
0          3          4          1          3          0          1          2  
1          3          4          1          3          0          0          3  
2          3          4          1          3          0          0          0  
3          3          3          1          3          0          1          2  
4          3          3          1          3          0          0          3  

答案 1 :(得分:0)

做一个大pd.concat()然后重命名所有列对你有用吗?类似的东西:

desired_columns = ['items', 'spend']
big_df = pd.concat([df1, df2[desired_columns], ..., dfN[desired_columns]], axis=1)


new_columns = ['org', 'name']
for i in range(num_dataframes):
    new_columns.extend(['spend_df%i' % i, 'items_df%i' % i])

bid_df.columns = new_columns

这应该为您提供如下列:

org, name, spend_df0, items_df0, spend_df1, items_df1, ..., spend_df8, items_df8

答案 2 :(得分:0)

我有时也想要这个,但却无法找到内置的熊猫方式。这是我的建议(以及我下次需要时的计划):

  1. 创建一个空字典merge_dict
  2. 遍历您想要的每个数据框的索引,并将所需的值添加到字典中,并将索引作为键。
  3. 生成新索引sorted(merge_dict)
  4. 通过循环merge_dict.items()为每列生成新的数据列表。
  5. 使用index=sorted(merge_dict)创建一个新数据框,并在上一步中创建列。
  6. 基本上,这有点像SQL中的散列连接。似乎是我能想到的最有效的方式,不应该花太长时间来编写代码。

    祝你好运。