पंडों ने तीन तरह से स्तंभों पर कई डेटाफ्रेमों को जोड़ा


191

मेरे पास 3 CSV फाइलें हैं। प्रत्येक में लोगों के नाम (स्ट्रिंग) के रूप में पहला कॉलम होता है, जबकि प्रत्येक डेटाफ्रेम में अन्य सभी कॉलम उस व्यक्ति के गुण होते हैं।

मैं व्यक्ति के स्ट्रिंग नाम के प्रत्येक अद्वितीय मान के लिए सभी विशेषताओं वाली प्रत्येक पंक्ति के साथ एक एकल CSV बनाने के लिए सभी तीन CSV दस्तावेज़ों को एक साथ "कैसे" जोड़ सकता हूँ?

join()पांडा निर्दिष्ट में समारोह मैं एक multiindex जरूरत है कि, लेकिन मैं क्या एक पदानुक्रमित अनुक्रमण योजना एक में शामिल होने के लिए एक एकल सूचकांक के आधार पर बनाने के साथ क्या करना है के बारे में उलझन में हूँ।


2
आपको एक मल्टीइन्डेक्स की आवश्यकता नहीं है। इसमें शामिल होने वाले डॉक्स में कहा गया है कि आपके पास एक मल्टीइन्डेक्स नहीं है, जब उस पर जुड़ने के लिए कई कॉलमों को पास करना होगा, तो वह इसे संभाल लेगा।
cwharland

1
मेरे परीक्षणों में, df1.join([df2, df3], on=[df2_col1, df3_col1])काम नहीं किया।
लॉलेरकोस्टर

आपको दिए गए उत्तर की तरह उन्हें एक साथ श्रृंखलाबद्ध करने की आवश्यकता है। मर्ज df1 और df2 तो df3 के साथ परिणाम मर्ज करें
cwharland

जवाबों:


473

मान लिया गया आयात:

import pandas as pd

जॉन गाल्ट का जवाब मूल रूप से एक reduceऑपरेशन है। अगर मेरे पास एक से अधिक डेटाफ्रेम हैं, तो मैं उन्हें इस तरह से सूची में डालूंगा (सूची समझ या लूप या व्हाट्सएप के माध्यम से उत्पन्न):

dfs = [df0, df1, df2, dfN]

मान लें कि उनके कुछ सामान्य कॉलम हैं, जैसे nameआपके उदाहरण में, मैं निम्नलिखित काम करूंगा:

df_final = reduce(lambda left,right: pd.merge(left,right,on='name'), dfs)

इस तरह, आपके कोड को उस संख्या के साथ काम करना चाहिए, जो भी डेटाफ़्रेम आप मर्ज करना चाहते हैं।

1 अगस्त 2016 को संपादित करें : पायथन 3 का उपयोग करने वालों के लिए: reduceमें स्थानांतरित कर दिया गया है functools। इसलिए इस फ़ंक्शन का उपयोग करने के लिए, आपको सबसे पहले उस मॉड्यूल को आयात करना होगा:

from functools import reduce

11
मैंने बस इसका उपयोग करने की कोशिश की और यह विफल हो reduceगया क्योंकि functools.reduceimport functools functools.reduce(.......)
मैट

3
यदि मैं शामिल होने के लिए खेतों के नाम अलग हैं तो यह समाधान कैसे काम करेगा? उदाहरण के लिए, तीन डेटा फ्रेम में मैं कर सकता था name1, name2और name3क्रमशः।
ps0604

2
इसका मतलब यह नहीं है कि हमारे पास n-1मर्ज फ़ंक्शन के लिए कॉल हैं? मुझे लगता है कि इस मामले में जहां डेटाफ्रेम की संख्या कम है, यह कोई फर्क नहीं पड़ता, लेकिन मुझे आश्चर्य है कि अगर कोई अधिक मापनीय समाधान है।
इपोलिनारियो

1
dfकॉलम मल्टी इंडेक्स के साथ यह मेरे लिए काफी काम नहीं था (यह 'ऑन' को एक कॉलम के रूप में इंजेक्ट कर रहा था, जो पहले मर्ज के लिए काम करता था, लेकिन बाद में विलय विफल हो गया), इसके बजाय मुझे इसके साथ काम करना पड़ा:df = reduce(lambda left, right: left.join(right, how='outer', on='Date'), dfs)
एड्रियन टॉरी

+1 से ps0604। क्या होगा अगर जॉइन कॉलम अलग हैं, क्या यह काम करता है? क्या हमें pd.merge के साथ जाना चाहिए जुड़ने वाले कॉलम अलग हैं? धन्यवाद
स्टीव

106

यदि आप 3 डेटाफ्रेम हैं, तो आप यह कोशिश कर सकते हैं

# Merge multiple dataframes
df1 = pd.DataFrame(np.array([
    ['a', 5, 9],
    ['b', 4, 61],
    ['c', 24, 9]]),
    columns=['name', 'attr11', 'attr12'])
df2 = pd.DataFrame(np.array([
    ['a', 5, 19],
    ['b', 14, 16],
    ['c', 4, 9]]),
    columns=['name', 'attr21', 'attr22'])
df3 = pd.DataFrame(np.array([
    ['a', 15, 49],
    ['b', 4, 36],
    ['c', 14, 9]]),
    columns=['name', 'attr31', 'attr32'])

pd.merge(pd.merge(df1,df2,on='name'),df3,on='name')

वैकल्पिक रूप से, जैसा कि cwharland द्वारा उल्लेख किया गया है

df1.merge(df2,on='name').merge(df3,on='name')

34
क्लीनर के लिए आप उन्हें चेन कर सकते हैं df1.merge(df2,on='name').merge(df3,on='name')
cwharland

1
यदि मैं शामिल होने के लिए खेतों के नाम अलग हैं तो यह समाधान कैसे काम करेगा? उदाहरण के लिए, तीन डेटा फ्रेम में name1, name2और name3क्रमशः
ps0604

4
@ ps0604df1.merge(df2,left_on='name1', right_on='name2').merge(df3,left_on='name1', right_on='name3').drop(columns=['name2', 'name3']).rename(columns={'name1':'name'})
माइकल एच।

और आगे, सूचकांक का उपयोग करके यह कैसे करें। काम करने के लिए प्रतीत नहीं होता है अगर 'नाम' सूचकांक है और स्तंभ नाम नहीं है।
ब्रायन डी

85

यह joinविधि के लिए एक आदर्श स्थिति है

इस joinप्रकार की स्थितियों के लिए विधि बिल्कुल निर्मित है। आप इसके साथ किसी भी संख्या में DataFrames को जोड़ सकते हैं। कॉलिंग डाटाफ्रेम पास किए गए डेटाफ्रेम के संग्रह के सूचकांक के साथ जुड़ जाता है। कई डेटाफ़्रेम के साथ काम करने के लिए, आपको सूचकांक में शामिल होने वाले कॉलम को रखना होगा।

कोड कुछ इस तरह दिखेगा:

filenames = ['fn1', 'fn2', 'fn3', 'fn4',....]
dfs = [pd.read_csv(filename, index_col=index_col) for filename in filenames)]
dfs[0].join(dfs[1:])

@ शून्य डेटा के साथ, आप ऐसा कर सकते हैं:

df1 = pd.DataFrame(np.array([
    ['a', 5, 9],
    ['b', 4, 61],
    ['c', 24, 9]]),
    columns=['name', 'attr11', 'attr12'])
df2 = pd.DataFrame(np.array([
    ['a', 5, 19],
    ['b', 14, 16],
    ['c', 4, 9]]),
    columns=['name', 'attr21', 'attr22'])
df3 = pd.DataFrame(np.array([
    ['a', 15, 49],
    ['b', 4, 36],
    ['c', 14, 9]]),
    columns=['name', 'attr31', 'attr32'])

dfs = [df1, df2, df3]
dfs = [df.set_index('name') for df in dfs]
dfs[0].join(dfs[1:])

     attr11 attr12 attr21 attr22 attr31 attr32
name                                          
a         5      9      5     19     15     49
b         4     61     14     16      4     36
c        24      9      4      9     14      9

4
खाली डेटाफ़्रेम में सभी dfs का जुड़ना भी काम करता है pd.DataFrame().join(dfs, how="outer"):। यह कुछ स्थितियों में क्लीनर हो सकता है।
डोमिनिक

4
यह उचित सलाह है और अब इसे 101 मर्जिंग पंडों में शामिल कर लिया गया है (देखें कई डेटाफ़्रेम विलय पर अनुभाग)। यह ध्यान देने योग्य है कि यदि आपकी ज्वाइन कीज़ यूनिक हैं, तो pd.concatसिंपल सिंटैक्स का उपयोग करेंगे pd.concat([df.set_index('name') for df in dfs], axis=1, join='inner').reset_index()concatयह भी अधिक बहुमुखी है जब कई dfs ( joinयह उतना अच्छा नहीं है) में डुप्लिकेट कॉलम नामों के साथ काम कर रहा है, हालांकि आप केवल इसके साथ आंतरिक या बाहरी जुड़ाव प्रदर्शन कर सकते हैं।
cs95

dfs[0].join(dfs[1:])के लिए संपादित किया जाना चाहिए dfs[0].join(dfs[1:], sort=False) क्योंकि अन्यथा FutureWarningपॉप जाएगा। अच्छे उदाहरण के लिए धन्यवाद।
gies0r

मुझे कोशिश करने पर एक त्रुटि मिलती है: ValueError: Indexes have overlapping valuesहालांकि, सूची में व्यक्तिगत डेटाफ्रेम के निरीक्षण से, उन्हें अतिव्यापी मान नहीं लगता है।
सोमजुरा

17

यह डेटाफ्रेम की सूची के लिए निम्नानुसार भी किया जा सकता है df_list:

df = df_list[0]
for df_ in df_list[1:]:
    df = df.merge(df_, on='join_col_name')

या यदि डेटाफ्रेम एक जेनरेटर ऑब्जेक्ट (जैसे मेमोरी खपत को कम करने के लिए) में हैं:

df = next(df_list)
for df_ in df_list:
    df = df.merge(df_, on='join_col_name')

11

में python3.6.3 के साथ pandas0.22.0 आप भी उपयोग कर सकते हैं concatजब तक आप कॉलम आप में शामिल होने के लिए उपयोग करना चाहते सूचकांक के रूप में सेट के रूप में

pd.concat(
    (iDF.set_index('name') for iDF in [df1, df2, df3]),
    axis=1, join='inner'
).reset_index()

जहाँ df1, df2और जॉन गाल्ट के उत्तर केdf3 रूप में परिभाषित किया गया है

import pandas as pd
df1 = pd.DataFrame(np.array([
    ['a', 5, 9],
    ['b', 4, 61],
    ['c', 24, 9]]),
    columns=['name', 'attr11', 'attr12']
)
df2 = pd.DataFrame(np.array([
    ['a', 5, 19],
    ['b', 14, 16],
    ['c', 4, 9]]),
    columns=['name', 'attr21', 'attr22']
)
df3 = pd.DataFrame(np.array([
    ['a', 15, 49],
    ['b', 4, 36],
    ['c', 14, 9]]),
    columns=['name', 'attr31', 'attr32']
)

2
यह स्वीकृत उत्तर होना चाहिए। यह सबसे तेज है।
आर। झू

4

एक को ऑपरेशन में शामिल होने के लिए एक मल्टीइन्डेक्स की आवश्यकता नहीं है । एक को बस इंडेक्स कॉलम को सही ढंग से सेट करने की आवश्यकता होती है, जिस पर शामिल होने के ऑपरेशन (जो कमांड करते हैंdf.set_index('Name') उदाहरण के लिए )

joinआपरेशन सूचकांक पर प्रदर्शन डिफ़ॉल्ट रूप से है। आपके मामले में, आपको बस यह बताना होगा किName कॉलम आपके सूचकांक से मेल खाता है। नीचे एक उदाहरण है

एक ट्यूटोरियल उपयोगी हो सकता है।

# Simple example where dataframes index are the name on which to perform the join operations
import pandas as pd
import numpy as np
name = ['Sophia' ,'Emma' ,'Isabella' ,'Olivia' ,'Ava' ,'Emily' ,'Abigail' ,'Mia']
df1 = pd.DataFrame(np.random.randn(8, 3), columns=['A','B','C'], index=name)
df2 = pd.DataFrame(np.random.randn(8, 1), columns=['D'],         index=name)
df3 = pd.DataFrame(np.random.randn(8, 2), columns=['E','F'],     index=name)
df = df1.join(df2)
df = df.join(df3)

# If you a 'Name' column that is not the index of your dataframe, one can set this column to be the index
# 1) Create a column 'Name' based on the previous index
df1['Name']=df1.index
# 1) Select the index from column 'Name'
df1=df1.set_index('Name')

# If indexes are different, one may have to play with parameter how
gf1 = pd.DataFrame(np.random.randn(8, 3), columns=['A','B','C'], index=range(8))
gf2 = pd.DataFrame(np.random.randn(8, 1), columns=['D'], index=range(2,10))
gf3 = pd.DataFrame(np.random.randn(8, 2), columns=['E','F'], index=range(4,12))

gf = gf1.join(gf2, how='outer')
gf = gf.join(gf3, how='outer')

4

यहां कॉलम नामों को डिक्शनरी के साथ रखते हुए डेटा फ़्रेमों के शब्दकोश को मर्ज करने की विधि दी गई है। यदि आवश्यक हो तो यह लापता मूल्यों में भी भर जाता है:

यह डेटा फ़्रेम के एक तानाशाह को मर्ज करने का कार्य है

def MergeDfDict(dfDict, onCols, how='outer', naFill=None):
  keys = dfDict.keys()
  for i in range(len(keys)):
    key = keys[i]
    df0 = dfDict[key]
    cols = list(df0.columns)
    valueCols = list(filter(lambda x: x not in (onCols), cols))
    df0 = df0[onCols + valueCols]
    df0.columns = onCols + [(s + '_' + key) for s in valueCols] 

    if (i == 0):
      outDf = df0
    else:
      outDf = pd.merge(outDf, df0, how=how, on=onCols)   

  if (naFill != None):
    outDf = outDf.fillna(naFill)

  return(outDf)

ठीक है, यह डेटा उत्पन्न करता है और इसका परीक्षण करता है:

def GenDf(size):
  df = pd.DataFrame({'categ1':np.random.choice(a=['a', 'b', 'c', 'd', 'e'], size=size, replace=True),
                      'categ2':np.random.choice(a=['A', 'B'], size=size, replace=True), 
                      'col1':np.random.uniform(low=0.0, high=100.0, size=size), 
                      'col2':np.random.uniform(low=0.0, high=100.0, size=size)
                      })
  df = df.sort_values(['categ2', 'categ1', 'col1', 'col2'])
  return(df)


size = 5
dfDict = {'US':GenDf(size), 'IN':GenDf(size), 'GER':GenDf(size)}   
MergeDfDict(dfDict=dfDict, onCols=['categ1', 'categ2'], how='outer', naFill=0)

3

सरल उपाय:

यदि स्तंभ नाम समान हैं:

 df1.merge(df2,on='col_name').merge(df3,on='col_name')

यदि स्तंभ नाम अलग हैं:

df1.merge(df2,left_on='col_name1', right_on='col_name2').merge(df3,left_on='col_name1', right_on='col_name3').drop(columns=['col_name2', 'col_name3']).rename(columns={'col_name1':'col_name'})

2

पंडों के प्रलेखन से एक और उपाय है (कि मैं यहाँ नहीं देखता),

का उपयोग करते हुए .append

>>> df = pd.DataFrame([[1, 2], [3, 4]], columns=list('AB'))
   A  B
0  1  2
1  3  4
>>> df2 = pd.DataFrame([[5, 6], [7, 8]], columns=list('AB'))
   A  B
0  5  6
1  7  8
>>> df.append(df2, ignore_index=True)
   A  B
0  1  2
1  3  4
2  5  6
3  7  8

ignore_index=True, संलग्न dataframe के सूचकांक की अनदेखी करने के स्रोत एक में उपलब्ध अगले सूचकांक और इसकी जगह प्रयोग किया जाता है।

यदि अलग-अलग कॉलम नाम हैं, Nanतो पेश किया जाएगा।


यह शब्दार्थ है, किसी के लिए "ज्वाइन" शब्द का उपयोग करके दो डेटाफ्रेम को एक साथ रखना। (एसक्यूएल जॉइन ऑपरेशन के रूप में जरूरी नहीं)
सिलहारे

1

तीन डेटाफ्रेम हैं

यहां छवि विवरण दर्ज करें

यहां छवि विवरण दर्ज करें

नेस्टेड pd.merge का उपयोग करके इन फ़्रेमों को मर्ज करें

यहां छवि विवरण दर्ज करें

यहां हम जाते हैं, हमारे पास हमारे मर्ज किए गए डेटाफ्रेम हैं।

खुश विश्लेषण !!!

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.