कैसे एक श्रृंखला और DataFrame मर्ज करने के लिए


83

यदि आप यहाँ और अनुक्रमणिका के विलय केDataFrameSeries बारे में जानकारी की तलाश में आए हैं , तो कृपया इस उत्तर को देखें

ओपी का मूल उद्देश्य यह पूछना था कि श्रृंखला के तत्वों को दूसरे डेटाफ़्रेम के कॉलम के रूप में कैसे निर्दिष्ट किया जाए । यदि आप इसका उत्तर जानने में रुचि रखते हैं, तो EdChum द्वारा स्वीकृत उत्तर को देखें।


सबसे अच्छा मैं साथ आ सकता हूं

df = pd.DataFrame({'a':[1, 2], 'b':[3, 4]})  # see EDIT below
s = pd.Series({'s1':5, 's2':6})

for name in s.index:
    df[name] = s[name]

   a  b  s1  s2
0  1  3   5   6
1  2  4   5   6

किसी को भी बेहतर वाक्यविन्यास / तेज विधि का सुझाव दे सकते हैं?

मेरे प्रयास:

df.merge(s)
AttributeError: 'Series' object has no attribute 'columns'

तथा

df.join(s)
ValueError: Other Series must have a name

संपादित करें पहले दो उत्तरों ने मेरे प्रश्न के साथ एक समस्या को उजागर किया, इसलिए निर्माण के लिए कृपया निम्नलिखित का उपयोग करें df:

df = pd.DataFrame({'a':[np.nan, 2, 3], 'b':[4, 5, 6]}, index=[3, 5, 6])

अंतिम परिणाम के साथ

    a  b  s1  s2
3 NaN  4   5   6
5   2  5   5   6
6   3  6   5   6

जवाबों:


26

आप श्रृंखला से एक डेटाफ़्रेम का निर्माण कर सकते हैं और फिर डेटाफ़्रेम के साथ विलय कर सकते हैं। इसलिए आप डेटा को मान के रूप में निर्दिष्ट करते हैं, लेकिन उन्हें लंबाई से गुणा करते हैं, कॉलम को इंडेक्स पर सेट करते हैं और बाएं_इंडेक्स और राइट_इंडेक्स के लिए ट्रू सेट करते हैं:

In [27]:

df.merge(pd.DataFrame(data = [s.values] * len(s), columns = s.index), left_index=True, right_index=True)
Out[27]:
   a  b  s1  s2
0  1  3   5   6
1  2  4   5   6

EDIT उस स्थिति के लिए जहां आप df के सूचकांक का उपयोग करने के लिए श्रृंखला से अपने निर्मित df के सूचकांक चाहते हैं, तो आप निम्न कार्य कर सकते हैं:

df.merge(pd.DataFrame(data = [s.values] * len(df), columns = s.index, index=df.index), left_index=True, right_index=True)

यह मानता है कि सूचकांक लंबाई से मेल खाते हैं।


168


V0.24.0 से अपडेट करें , जब तक श्रृंखला का नाम है, तब तक आप DataFrame और Series पर विलय कर सकते हैं।

df.merge(s.rename('new'), left_index=True, right_index=True)
# If series is already named,
# df.merge(s, left_index=True, right_index=True)

आजकल, आप सिरीज को डेटाफ़्रेम में the_frame () के साथ बदल सकते हैं । इसलिए (यदि इंडेक्स में शामिल हो रहे हैं):

df.merge(s.to_frame(), left_index=True, right_index=True)

6
प्रश्न की परिभाषा का उपयोग करते हुए dfऔर s, यह उत्तर मेरे लिए एक खाली डेटाफ़्रेम देता है, कि प्रश्न में अनुरोधित परिणाम। हम सूचकांक पर मेल नहीं खाना चाहते हैं; हम sसभी पंक्तियों के मानों को प्रसारित करना चाहते हैं df
सीपीबीएल

2
यह एक अलग समस्या को हल कर रहा है: "एक DataFrame और Series को देखते हुए, उन्हें इंडेक्स पर कैसे मर्ज किया जा सकता है"। ओपी का सवाल था "एक सीरीज़ के प्रत्येक तत्व को डेटाफ़्रेम में एक नए कॉलम के रूप में असाइन करें"।
cs95

5

यहाँ एक तरीका है:

df.join(pd.DataFrame(s).T).fillna(method='ffill')

टूटने के लिए यहां क्या होता है ...

pd.DataFrame(s).Tएक-पंक्ति DataFrame बनाता है sजिससे यह दिखता है:

   s1  s2
0   5   6

इसके बाद, joinइस नए फ्रेम को df:

   a  b  s1  s2
0  1  3   5   6
1  2  4 NaN NaN

अंत में, NaNइंडेक्स 1 के मानों fillnaको आगे-भरण ( ffill) तर्क के साथ उपयोग करते हुए कॉलम में पिछले मानों से भरा जाता है:

   a  b  s1  s2
0  1  3   5   6
1  2  4   5   6

उपयोग करने से बचने के लिए fillna, इससे pd.concatनिर्मित डेटाफ़्रेम की पंक्तियों को दोहराने के लिए उपयोग करना संभव है s। इस मामले में, सामान्य समाधान है:

df.join(pd.concat([pd.DataFrame(s).T] * len(df), ignore_index=True))

संपादित प्रश्न में अनुक्रमित चुनौती को संबोधित करने के लिए यहां एक और समाधान दिया गया है:

df.join(pd.DataFrame(s.repeat(len(df)).values.reshape((len(df), -1), order='F'), 
        columns=s.index, 
        index=df.index))

sमूल्यों को फिर से शुरू करके और 'फोरट्रान' को निर्दिष्ट करते हुए), और उपयुक्त कॉलम नामों और सूचकांक में पास करके डेटाफ़्रेम में बदल दिया जाता है। यह नया DataFrame तब शामिल हो गया है df


अच्छा वन-लाइनर, एक चेतावनी है कि किसी भी NaN के पहले से ही df में भी भर जाएगा।
नाथन लॉयड

@Nonth धन्यवाद और अच्छी बात। मैंने एक विकल्प शामिल करने के लिए संपादित किया है जो NaNमूल्यों में भरने से बचता है ।
एलेक्स रिले

एडचम्स के मूल उत्तर के साथ जो हुआ वह इस संशोधित उत्तर को प्रभावित करता है। यदि मैं df के साथ निर्माण करता हूं, तो कहो, index=[3, 5]नए कॉलम में आपके आदेश के बाद नैनो है।
नाथन लॉयड

@Nonth फिर से संपादित किया गया! इसे अब आपकी नई आवश्यकताओं को पूरा करना चाहिए।
एलेक्स रिले

आपका उत्तर 20x तेज है, लेकिन यह अभी भी 1e5 पंक्तियों में df के साथ ~ 100ms का अंतर है। मेरे लिए लूप क्षैतिज रूप से धीमा है। आपके जवाब में BTW आमतौर पर लागू 2होना चाहिए len(df)
नाथन लॉयड

0

अगर मैं आपके डेटाफ्रेम को इस तरह सेट करने का सुझाव दे सकता हूं (ऑटो-इंडेक्सिंग):

df = pd.DataFrame({'a':[np.nan, 1, 2], 'b':[4, 5, 6]})

तब आप अपने s1 और s2 मान इस प्रकार सेट कर सकते हैं (df से पंक्तियों की संख्या लौटाने के लिए आकार () का उपयोग करके):

s = pd.DataFrame({'s1':[5]*df.shape[0], 's2':[6]*df.shape[0]})

फिर जो परिणाम आप चाहते हैं वह आसान है:

display (df.merge(s, left_index=True, right_index=True))

वैकल्पिक रूप से, बस अपने डेटाफ़्रेम df में नए मान जोड़ें:

df = pd.DataFrame({'a':[nan, 1, 2], 'b':[4, 5, 6]})
df['s1']=5
df['s2']=6
display(df)

दोनों वापस:

     a  b  s1  s2
0  NaN  4   5   6
1  1.0  5   5   6
2  2.0  6   5   6

यदि आपके पास डेटा की एक और सूची है (लागू करने के लिए केवल एक मान के बजाय), और आप जानते हैं कि यह उसी क्रम में है, जैसे कि:

s1=['a','b','c']

तो आप इसे उसी तरह से संलग्न कर सकते हैं:

df['s1']=s1

रिटर्न:

     a  b s1
0  NaN  4  a
1  1.0  5  b
2  2.0  6  c

0

आप आसानी से एक pandas.DataFrame कॉलम को स्थिरांक पर सेट कर सकते हैं। यह निरंतर एक उदाहरण के रूप में आपके उदाहरण में हो सकता है। यदि आपके द्वारा निर्दिष्ट कॉलम df में नहीं है, तो पांडा आपके द्वारा निर्दिष्ट नाम के साथ एक नया कॉलम बनाएगा। तो आपके डेटाफ़्रेम के निर्माण के बाद, (आपके प्रश्न से):

df = pd.DataFrame({'a':[np.nan, 2, 3], 'b':[4, 5, 6]}, index=[3, 5, 6])

आप बस चला सकते हैं:

df['s1'], df['s2'] = 5, 6

आप एक लूप या समझ लिख सकते हैं कि यह सभी तत्वों के लिए एक सूची में ट्यूपल्स या कुंजियों और मानों के लिए ऐसा कर सकता है, जो आपके वास्तविक डेटा को संग्रहीत करने के आधार पर करता है।


0

यदि dfएक है, pandas.DataFrameतो df['new_col']= Series list_object of length len(df)एक स्तंभ के रूप में या Series list_object जोड़ देगा 'new_col'df['new_col']= scalar(जैसे आपके मामले में 5 या 6) भी काम करता है और इसके बराबर हैdf['new_col']= [scalar]*len(df)

तो एक दो-लाइन कोड उद्देश्य को पूरा करता है:

df = pd.DataFrame({'a':[1, 2], 'b':[3, 4]})
s = pd.Series({'s1':5, 's2':6})
for x in s.index:    
    df[x] = s[x]

Output: 
   a  b  s1  s2
0  1  3   5   6
1  2  4   5   6
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.