Python: pandas объединяет несколько фреймов данных

У меня есть разные файлы данных, и вам нужно объединить их вместе на основе столбца даты. Если бы у меня было только два файла, я мог бы использовать df1.merge(df2, on='date') , если я попробую с тремя файлами, я использую df1.merge(df2.merge(df3, on='date'), on='date') , но для слияния нескольких файлов.

Кадры данных имеют один столбец, общий – «дата», но не имеют одинакового количества строк или столбцов, и мне нужны только даты, общие для каждого фрейма данных.

Итак, я пытаюсь написать функцию рекурсии, которая возвращает фреймворк данных со всеми данными, но это не сработало. Как объединить несколько фреймов данных?

Я пробовал разные способы и получал такие ошибки, как out of range , keyerror 0/1/2/3 и can not merge DataFrame with instance of type <class 'NoneType'> .

Это сценарий:

 dfs = [df1, df2, df3] # list of dataframes def mergefiles(dfs, countfiles, i=0): if i == (countfiles - 2): # it gets to the second to last and merges it with the last return dfm = dfs[i].merge(mergefiles(dfs[i+1], countfiles, i=i+1), on='date') return dfm print(mergefiles(dfs, len(dfs))) 

Пример: file_1:

 May 19, 2017;1,200.00;0.1% May 18, 2017;1,100.00;0.1% May 17, 2017;1,000.00;0.1% May 15,2017;900.00;0.2% 

file_2:

 May 20, 2017;2,200.00;1000000;0.2% May 18, 2017;2,100.00;1590000;0.2% May 16, 2017;2,000.00;1230000;0.2% May 15,2017;1,900.00;1000000;0.2% 

file_3:

 May 21, 2017;3,200.00;2000000;0.2% May 17, 2017;3,100.00;2590000;0.2% May 16, 2017;3,000.00;2230000;0.2% May 15,2017;2,900.00;2000000;0.2% 

Ожидаемый результат слияния:

 May 15,2017;2,900.00;2000000;0.2% 

Ниже приведен самый чистый и понятный способ слияния нескольких кадров данных, если сложные запросы не задействованы.

Просто просто слияние с DATE как индекс и слияние с использованием метода OUTER (чтобы получить все данные).

  import pandas as pd; from functools import reduce; df1 = pd.read_table('file1.csv', sep=',') df2 = pd.read_table('file2.csv', sep=',') df3 = pd.read_table('file3.csv', sep=',') 

Итак, в основном загрузите все файлы, которые у вас есть в качестве фрейма данных. Затем объедините файлы с помощью функции merge или reduce .

 # compile the list of dataframes you want to merge data_frames = [df1, df2, df3] 

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

Чтобы сохранить значения, принадлежащие одной и той же дате, вам необходимо объединить их в DATE

 df_merged = reduce(lambda left,right: pd.merge(left,right,on=['DATE'], how='outer'), data_frames) # if you want to fill the values that don't exist in the lines of merged dataframe simply fill with required strings as df_merged = reduce(lambda left,right: pd.merge(left,right,on=['DATE'], how='outer'), data_frames).fillna('void') 
  • Таким образом, значения с той же даты находятся на одной линии.
  • Вы можете заполнить несуществующие данные из разных фреймов для разных столбцов, используя fillna ().

Затем, если нужно, напишите объединенные данные в файл csv.

 pd.DataFrame.to_csv(df_merged, 'merged.txt', sep=',', na_rep='.', index=False) 

Это должно дать вам

DATE VALUE1 VALUE2 VALUE3 ....

Для этого есть 2 решения, но они возвращают все столбцы отдельно:

 import functools dfs = [df1, df2, df3] df_final = functools.reduce(lambda left,right: pd.merge(left,right,on='date'), dfs) print (df_final) date a_x b_x a_y b_y c_x ab c_y 0 May 15,2017 900.00 0.2% 1,900.00 1000000 0.2% 2,900.00 2000000 0.2% k = np.arange(len(dfs)).astype(str) df = pd.concat([x.set_index('date') for x in dfs], axis=1, join='inner', keys=k) df.columns = df.columns.map('_'.join) print (df) 0_a 0_b 1_a 1_b 1_c 2_a 2_b 2_c date May 15,2017 900.00 0.2% 1,900.00 1000000 0.2% 2,900.00 2000000 0.2% 

Если вы фильтруете по общей дате, это вернет его:

 dfs = [df1, df2, df3] checker = dfs[-1] check = set(checker.loc[:, 0]) for df in dfs[:-1]: check = check.intersection(set(df.loc[:, 0])) print(checker[checker.loc[:, 0].isin(check)]) 

Похоже, данные имеют одинаковые столбцы, поэтому вы можете:

 df1 = pd.DataFrame(data1) df2 = pd.DataFrame(data2) merged_df = pd.concat([df1, df2]) 

Ответ @ даннейу правильный. pd.concat, естественно, присоединяется к столбцам индекса, если вы установите опцию оси в 1. По умолчанию используется внешнее соединение, но вы также можете указать внутреннее соединение. Вот пример:

 x = pd.DataFrame({'a': [2,4,3,4,5,2,3,4,2,5], 'b':[2,3,4,1,6,6,5,2,4,2], 'val': [1,4,4,3,6,4,3,6,5,7], 'val2': [2,4,1,6,4,2,8,6,3,9]}) x.set_index(['a','b'], inplace=True) x.sort_index(inplace=True) y = x.__deepcopy__() y.loc[(14,14),:] = [3,1] y['other']=range(0,11) y.sort_values('val', inplace=True) z = x.__deepcopy__() z.loc[(15,15),:] = [3,4] z['another']=range(0,22,2) z.sort_values('val2',inplace=True) pd.concat([x,y,z],axis=1) 

Я благодарю вас за вашу помощь @jezrael , @zipa и @ everestial007 , оба ответа – это то, что мне нужно. Если бы я был рекурсивным, это также работало бы по назначению:

 def mergefiles(dfs=[], on=''): """Merge a list of files based on one column""" if len(dfs) == 1: return "List only have one element." elif len(dfs) == 2: df1 = dfs[0] df2 = dfs[1] df = df1.merge(df2, on=on) return df # Merge the first and second datafranes into new dataframe df1 = dfs[0] df2 = dfs[1] df = dfs[0].merge(dfs[1], on=on) # Create new list with merged dataframe dfl = [] dfl.append(df) # Join lists dfl = dfl + dfs[2:] dfm = mergefiles(dfl, on) return dfm 
Interesting Posts