2017-06-02 14 views
5

मेरे पास डेटा की अलग-अलग फ़ाइलें हैं और उन्हें दिनांक कॉलम के आधार पर एक साथ मर्ज करने की आवश्यकता है। अगर मेरे पास केवल दो फाइलें थीं, तो मैं 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% 
+0

और आपका अपेक्षित परिणाम क्या है? – zipa

+0

@zipa, बस पोस्ट संपादित किया। मर्ज परिणाम अपेक्षित परिणाम है। –

+0

उत्तर की जांच करें। सबसे समझदार और आसान एक। – everestial007

उत्तर

6

नीचे जटिल प्रश्न शामिल नहीं होने पर एकाधिक डेटाफ्रेम विलय करने का सबसे साफ, समझदार तरीका है।

बस बस सूचकांक के रूप में DATE के के साथ विलय और (सभी डेटा प्राप्त करने के लिए) बाहरी विधि का उपयोग कर देते हैं।

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() का उपयोग कर अलग-अलग कॉलम के लिए अलग-अलग फ्रेम से गैर मौजूदा डेटा भर सकते हैं।

फिर इच्छित होने पर विलय डेटा को सीएसवी फ़ाइल में लिखें।

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

यह आपको देना चाहिए

DATE VALUE1 VALUE2 VALUE3 ....

+0

आपकी मदद के लिए धन्यवाद, वास्तव में यह वास्तव में साफ है और इरादे से काम करता है। –

2

इस के लिए 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   a  b 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% 
1

आप आम तारीख के आधार पर फ़िल्टर रहे हैं, तो यह यह वापस आ जाएगी:

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)]) 
+0

लेकिन इस तरह से यह केवल 3 फाइलों के लिए परिणाम प्राप्त कर सकते हैं। अगर मैं 4 फाइलों के साथ प्रयास करता हूं तो क्या होगा? क्या मुझे करने की ज़रूरत है: 'सेट (df1.loc [:, 0] .intersection (सेट (df3.loc [:, 0])। चौराहे (सेट (df2.loc [:, 0]))। चौराहे (सेट (df1.loc [:, 0]))) '? –

+0

@ वास्को फ़ेरेराइरा मैंने उस स्थिति से मेल खाने के लिए कोड संपादित किया। – zipa

1

लग रहा है डेटा की तरह वही कॉलम है, तो आप कर सकते हैं:

df1 = pd.DataFrame(data1) 
df2 = pd.DataFrame(data2) 

merged_df = pd.concat([df1, df2]) 
0

मैं तुम्हारी मदद की @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 
1

@ डैन्यूयू का जवाब सही है। यदि आप अक्ष विकल्प को 1 पर सेट करते हैं तो pd.concat स्वाभाविक रूप से इंडेक्स कॉलम पर जुड़ता है। डिफ़ॉल्ट एक बाहरी जुड़ाव है, लेकिन आप आंतरिक भी शामिल कर सकते हैं। यहां एक उदाहरण दिया गया है:

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) 
संबंधित मुद्दे