पंडों ने सूचियों के स्तंभ को कई स्तंभों में विभाजित किया


135

मेरे पास एक कॉलम के साथ एक पांडा डेटाफ़्रेम है:

import pandas as pd

df = pd.DataFrame(
    data={
        "teams": [
            ["SF", "NYG"],
            ["SF", "NYG"],
            ["SF", "NYG"],
            ["SF", "NYG"],
            ["SF", "NYG"],
            ["SF", "NYG"],
            ["SF", "NYG"],
        ]
    }
)

print(df)

आउटपुट:

       teams
0  [SF, NYG]
1  [SF, NYG]
2  [SF, NYG]
3  [SF, NYG]
4  [SF, NYG]
5  [SF, NYG]
6  [SF, NYG]

सूचियों के इस स्तंभ को 2 कॉलमों में कैसे विभाजित किया जा सकता है?

जवाबों:


243

आप द्वारा बनाए गए DataFrameनिर्माण का उपयोग कर सकते हैं :liststo_list

import pandas as pd

d1 = {'teams': [['SF', 'NYG'],['SF', 'NYG'],['SF', 'NYG'],
                ['SF', 'NYG'],['SF', 'NYG'],['SF', 'NYG'],['SF', 'NYG']]}
df2 = pd.DataFrame(d1)
print (df2)
       teams
0  [SF, NYG]
1  [SF, NYG]
2  [SF, NYG]
3  [SF, NYG]
4  [SF, NYG]
5  [SF, NYG]
6  [SF, NYG]

df2[['team1','team2']] = pd.DataFrame(df2.teams.tolist(), index= df2.index)
print (df2)
       teams team1 team2
0  [SF, NYG]    SF   NYG
1  [SF, NYG]    SF   NYG
2  [SF, NYG]    SF   NYG
3  [SF, NYG]    SF   NYG
4  [SF, NYG]    SF   NYG
5  [SF, NYG]    SF   NYG
6  [SF, NYG]    SF   NYG

और नए के लिए DataFrame:

df3 = pd.DataFrame(df2['teams'].to_list(), columns=['team1','team2'])
print (df3)
  team1 team2
0    SF   NYG
1    SF   NYG
2    SF   NYG
3    SF   NYG
4    SF   NYG
5    SF   NYG
6    SF   NYG

समाधान apply(pd.Series)बहुत धीमा है:

#7k rows
df2 = pd.concat([df2]*1000).reset_index(drop=True)

In [121]: %timeit df2['teams'].apply(pd.Series)
1.79 s ± 52.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [122]: %timeit pd.DataFrame(df2['teams'].to_list(), columns=['team1','team2'])
1.63 ms ± 54.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

4
माइनर कैविट, यदि आप इसे मौजूदा डेटाफ़्रेम पर उपयोग कर रहे हैं, तो अनुक्रमणिका को रीसेट करना सुनिश्चित करें, अन्यथा यह सही ढंग से असाइन नहीं होगा।
15:17 बजे user1700890

1
@ user1700890 - हां, या डेटाफ्रेम कंस्ट्रक्टर में इंडेक्स निर्दिष्ट करेंdf2[['team1','team2']] = pd.DataFrame(df2.teams.values.tolist(), index= df2.index)
jezrael

1
@ कैटिगरीब - हां, अगर मौजूद सॉल्यूशंस सॉल्व करें तो सबसे अच्छा इससे बचें।
१२:०

1
@ कैटिगरी - हां, जाहिर है। सदिश का अर्थ है आम तौर पर कोई छोर नहीं, इसलिए कोई भी लागू नहीं, कोई सूची नहीं। लेकिन यह निर्भर करता है कि वास्तव में क्या जरूरत है। शायद यह भी मदद करता है
jezrael

2
@ कैटिगरी वास्तव में apply()धीमी हो सकती है लेकिन गो-टू विधि है जब इनपुट स्ट्रिंग और मान मूल श्रृंखला की पंक्तियों के बराबर नहीं होते हैं!
चेस्टास्टा

52

बहुत सरल उपाय:

pd.DataFrame(df2["teams"].to_list(), columns=['team1', 'team2'])

पैदावार,

  team1 team2
-------------
0    SF   NYG
1    SF   NYG
2    SF   NYG
3    SF   NYG
4    SF   NYG
5    SF   NYG
6    SF   NYG
7    SF   NYG

यदि आप सूचियों के बजाय सीमांकित तारों के एक स्तंभ को विभाजित करना चाहते हैं, तो आप भी ऐसा कर सकते हैं:

pd.DataFrame(df["teams"].str.split('<delim>', expand=True).values,
             columns=['team1', 'team2'])

6
क्या होगा यदि प्रत्येक सूची में असमान तत्वों की संख्या हो?
इक़ेल नोव

यदि आप सूचियों के बजाय सीमांकित तारों के एक स्तंभ को विभाजित करना चाहते थे, तो आप भी ऐसा df["teams"].str.split('<delim>', expand=True) ही कर सकते हैं: पहले से ही एक DataFrame लौटाता है, इसलिए संभवतः स्तंभों का नाम बदलना सरल होगा।
एएमसी

26

यह समाधान df2उपयोग किए जाने वाले किसी भी समाधान के विपरीत, डेटाफ्रेम के सूचकांक को संरक्षित करता है tolist():

df3 = df2.teams.apply(pd.Series)
df3.columns = ['team1', 'team2']

यहाँ परिणाम है:

  team1 team2
0    SF   NYG
1    SF   NYG
2    SF   NYG
3    SF   NYG
4    SF   NYG
5    SF   NYG
6    SF   NYG

2
साथ ही applyआप पंडों में सबसे धीमे काम कर सकते हैं। आपको इस विधि से बचना चाहिए और स्वीकृत उत्तर का उपयोग करना चाहिए। शीर्ष जवाब के समय में, इस पद्धति के लगभग है 1400 xधीमी @rajan
Erfan

2
@ इरफ़ान हाँ, लेकिन कभी-कभी उपयोगकर्ता को यह परवाह नहीं होती है कि क्या कोई ऑपरेशन 1s या 1ms लेता है, और इसके बजाय वे सबसे सरल, सबसे पठनीय कोड लिखने के बारे में सबसे ज्यादा परवाह करते हैं! मैं स्वीकार करता हूं कि पठनीयता / सरलता व्यक्तिपरक है, लेकिन मेरी बात बस इतनी है कि गति सभी उपयोगकर्ताओं के लिए हर समय प्राथमिकता नहीं है।
केविन मार्खम

1
इसके अलावा, मुझे पता चला कि applyबड़े डेटा सेट पर बड़े सरणियों (1000+ आइटम) के विस्तार के लिए विधि अधिक मज़बूती से काम करती है। tolist()विधि मेरी प्रक्रिया को मार डाला जब डेटा सेट 500k पंक्तियों से अधिक था।
मोरिट्ज़

2
यह एक महान समाधान है क्योंकि यह विभिन्न आकारों की सूचियों के साथ अच्छी तरह से काम करता है।
dasilvadaniel

@KevinMarkham वे सबसे सरल, सबसे पठनीय कोड लिखने के बारे में परवाह करते हैं क्या pd.DataFrame(df["teams"].to_list(), columns=["team_1", "team_2"])वास्तव में इतना अधिक जटिल है?
एएमसी

15

प्रस्तावित समाधानों के विपरीत, सिंटैक्टिक रूप से सरल तरीका लगता है, और इसलिए याद रखना आसान है। मैं मान रहा हूं कि डेटाफ़्रेम df में कॉलम को 'मेटा' कहा जाता है:

df2 = pd.DataFrame(df['meta'].str.split().values.tolist())

1
मुझे एक त्रुटि मिली लेकिन मैंने इसे हटाकर इसे हल कर दिया str.split()। यह बहुत सरल था और अगर आपकी सूची में वस्तुओं की संख्या नहीं पता है तो इसका फायदा है।
ओटेचेंग

प्रस्तावित समाधानों के विपरीत, सिंटैक्टिक रूप से सरल तरीका लगता है, और इसलिए याद रखना आसान है। वास्तव में? क्योंकि यह व्यावहारिक रूप से शीर्ष उत्तर के समान है जो वर्षों पहले पोस्ट किया गया था। एकमात्र अंतर वह हिस्सा है जो इस विशिष्ट प्रश्न से संबंधित नहीं है।
एएमसी

यह मेरे लिए काम करता है !!
एडुआर्डोउस्तारेज़

3

पिछले उत्तरों के आधार पर, यहां एक और समाधान दिया गया है जो df2.teams.apply (pd.Series) के समान परिणाम देता है जो बहुत तेजी से चलता है:

pd.DataFrame([{x: y for x, y in enumerate(item)} for item in df2['teams'].values.tolist()], index=df2.index)

समय:

In [1]:
import pandas as pd
d1 = {'teams': [['SF', 'NYG'],['SF', 'NYG'],['SF', 'NYG'],
                ['SF', 'NYG'],['SF', 'NYG'],['SF', 'NYG'],['SF', 'NYG']]}
df2 = pd.DataFrame(d1)
df2 = pd.concat([df2]*1000).reset_index(drop=True)

In [2]: %timeit df2['teams'].apply(pd.Series)

8.27 s ± 2.73 s per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [3]: %timeit pd.DataFrame([{x: y for x, y in enumerate(item)} for item in df2['teams'].values.tolist()], index=df2.index)

35.4 ms ± 5.22 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

3

उपरोक्त समाधान मेरे लिए कारगर नहीं थे क्योंकि मेरे पास nanअवलोकन हैं dataframe। मेरे मामले में df2[['team1','team2']] = pd.DataFrame(df2.teams.values.tolist(), index= df2.index)पैदावार:

object of type 'float' has no len()

मैं सूची समझ का उपयोग करके इसे हल करता हूं। यहाँ उदाहरण योग्य उदाहरण:

import pandas as pd
import numpy as np
d1 = {'teams': [['SF', 'NYG'],['SF', 'NYG'],['SF', 'NYG'],
            ['SF', 'NYG'],['SF', 'NYG'],['SF', 'NYG'],['SF', 'NYG']]}
df2 = pd.DataFrame(d1)
df2.loc[2,'teams'] = np.nan
df2.loc[4,'teams'] = np.nan
df2

उत्पादन:

        teams
0   [SF, NYG]
1   [SF, NYG]
2   NaN
3   [SF, NYG]
4   NaN
5   [SF, NYG]
6   [SF, NYG]

df2['team1']=np.nan
df2['team2']=np.nan

सूची समझ के साथ हल करना:

for i in [0,1]:
    df2['team{}'.format(str(i+1))]=[k[i] if isinstance(k,list) else k for k in df2['teams']]

df2

पैदावार:

    teams   team1   team2
0   [SF, NYG]   SF  NYG
1   [SF, NYG]   SF  NYG
2   NaN        NaN  NaN
3   [SF, NYG]   SF  NYG
4   NaN        NaN  NaN
5   [SF, NYG]   SF  NYG
6   [SF, NYG]   SF  NYG

1

सूची की समझ

सूची समझ के साथ सरल कार्यान्वयन (मेरा पसंदीदा)

df = pd.DataFrame([pd.Series(x) for x in df.teams])
df.columns = ['team_{}'.format(x+1) for x in df.columns]

उत्पादन पर समय:

CPU times: user 0 ns, sys: 0 ns, total: 0 ns
Wall time: 2.71 ms

उत्पादन:

team_1  team_2
0   SF  NYG
1   SF  NYG
2   SF  NYG
3   SF  NYG
4   SF  NYG
5   SF  NYG
6   SF  NYG

इस तरह के हैंडल अलग-अलग लंबाई की सूचियों की सूची बनाते हैं - जो कई अन्य उत्तरों पर सुधार है, लेकिन आइटम अपने स्वयं के कॉलम में नहीं होने के परिणामस्वरूप।
इसहाक

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