Я хотел бы объединить девять фреймов данных Pandas в один фрейм данных, выполняя объединение двух столбцов, контролируя имена столбцов. Это возможно?

У меня девять наборов данных. Все они имеют следующие столбцы:

org, name, items,spend

Я хочу объединить их в один фрейм данных со следующими столбцами:

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

Я читал документацию по объединению и присоединению. В настоящее время я могу объединить два набора данных следующим образом:

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, кажется, принимает только два за раз, и если я сделаю это последовательно, имена моих столбцов окажутся очень грязными.

6
Richard 17 Дек 2015 в 18:54

3 ответа

Лучший ответ

Вы можете использовать functools.reduce для многократного применения {{ X1}} к каждому из фреймов данных:

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  
7
unutbu 17 Дек 2015 в 19:18

Время от времени я тоже этого хотел, но не смог найти встроенного способа сделать это пандами. Вот мое предложение (и мой план на следующий раз, когда он мне понадобится):

  1. Создайте пустой словарь, merge_dict.
  2. Переберите нужный вам индекс для каждого из ваших фреймов данных и добавьте нужные значения в словарь с индексом в качестве ключа.
  3. Создайте новый индекс как sorted(merge_dict).
  4. Создайте новый список данных для каждого столбца, просматривая merge_dict.items ().
  5. Создайте новый фрейм данных с index=sorted(merge_dict) и столбцами, созданными на предыдущем шаге.

По сути, это что-то вроде хеш-соединения в SQL. Похоже, самый эффективный способ, который я могу придумать, и не должен занимать слишком много времени для написания кода.

Удачи.

0
Cmdt.Ed 5 Апр 2016 в 13:21

Подойдет ли вам большой 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

0
Zachary Cross 17 Дек 2015 в 16:25