किसी कॉलम को दो कॉलम में कैसे विभाजित करें?


197

मेरे पास एक कॉलम के साथ एक डेटा फ्रेम है और मैं इसे दो कॉलम में विभाजित करना चाहूंगा, जिसमें एक कॉलम हेडर है ' fips'और दूसरा'row'

मेरा डेटाफ़्रेम dfइस तरह दिखता है:

          row
0    00000 UNITED STATES
1    01000 ALABAMA
2    01001 Autauga County, AL
3    01003 Baldwin County, AL
4    01005 Barbour County, AL

मुझे पता नहीं है कि df.row.str[:]पंक्ति सेल को विभाजित करने के अपने लक्ष्य को प्राप्त करने के लिए कैसे उपयोग किया जाए। मैं df['fips'] = helloएक नया कॉलम जोड़ने और इसे पॉप्युलेट करने के लिए उपयोग कर सकता हूं hello। कोई विचार?

         fips       row
0    00000 UNITED STATES
1    01000 ALABAMA 
2    01001 Autauga County, AL
3    01003 Baldwin County, AL
4    01005 Barbour County, AL

3
आपने अपने डेटा को पांडा में कैसे लोड किया? आप का उपयोग करके वांछित प्रारूप में डेटा laod करने के लिए सक्षम हो सकता है read_table()या read_fwf()
Zach

जवाबों:


138

एक बेहतर तरीका हो सकता है, लेकिन यह यहां एक दृष्टिकोण है:

                            row
    0       00000 UNITED STATES
    1             01000 ALABAMA
    2  01001 Autauga County, AL
    3  01003 Baldwin County, AL
    4  01005 Barbour County, AL
df = pd.DataFrame(df.row.str.split(' ',1).tolist(),
                                 columns = ['flips','row'])
   flips                 row
0  00000       UNITED STATES
1  01000             ALABAMA
2  01001  Autauga County, AL
3  01003  Baldwin County, AL
4  01005  Barbour County, AL

6
ध्यान रखें कि .tolist () आपके पास मौजूद किसी भी इंडेक्स को हटा देगा, इसलिए आपका नया डेटाफ्रेम 0 से रिइंडैक्स हो जाएगा (यह आपके विशिष्ट मामले में कोई फर्क नहीं पड़ता)।
क्रैशहट

10
@ क्रशटच - फिर फिर से आप बस जोड़ सकते हैं index = df.indexऔर आप अच्छे हैं।
रूट

क्या होगा अगर एक सेल विभाजित नहीं किया जा सकता है?
निस्बा

@ निस्बा: यदि किसी सेल को विभाजित नहीं किया जा सकता है (जैसे कि स्ट्रिंग में इस मामले के लिए कोई स्थान नहीं है) तो यह अभी भी काम करेगा लेकिन विभाजन का एक हिस्सा खाली होगा। यदि आपके पास स्तंभ में मिश्रित प्रकार हैं, तो कम से कम एक सेल में किसी भी संख्या प्रकार के साथ अन्य स्थितियां होंगी। फिर splitविधि NaN लौटाती है और tolistविधि इस मान को वापस करेगी (NaN) जिसके परिणामस्वरूप ValueError(इस समस्या को दूर करने के लिए आप इसे विभाजित करने से पहले स्ट्रिंग प्रकार में डाल सकते हैं)। मैं आपको इसे अपने दम पर आजमाने की सलाह देता हूं। यह सीखने का सबसे अच्छा तरीका है :-)
नेरक्सिस

@techkuz: क्या आपको यकीन है कि आपके dfपास rowकॉलम हैडर है? आप सोच सकते हैं कि यह किसी प्रकार का DataFrame विशेषता है, लेकिन यह स्पष्ट है कि यह कॉलम का नाम है। यह आपके ऊपर है कि आप अपने कॉलम हेडर को कैसे बनाते हैं और परिभाषित करते हैं, यदि आप इसका उपयोग करते हैं तो इसका उपयोग करें (जैसे df.my_column_name.split(...))।
नेरक्सिस

390

TL; DR संस्करण:

के साधारण मामले के लिए:

  • मेरे पास एक टेक्स्ट कॉलम है जिसमें एक सीमांकक है और मुझे दो कॉलम चाहिए

सबसे सरल उपाय है:

df['A'], df['B'] = df['AB'].str.split(' ', 1).str

या आप विभाजन के प्रत्येक प्रविष्टि के लिए एक कॉलम के साथ एक DataFrame बना सकते हैं:

df['AB'].str.split(' ', 1, expand=True)

expand=Trueयदि आपके स्ट्रिंग्स में गैर-समान संख्या में विभाजन हैं और आप Noneलापता मानों को बदलना चाहते हैं तो आपको इसका उपयोग करना चाहिए ।

ध्यान दें कि, किसी भी स्थिति में, .tolist()विधि आवश्यक नहीं है। न ही है zip()

विस्तार से:

str.extract()विधि की शक्ति का प्रदर्शन करने में एंडी हेडन का समाधान सबसे उत्कृष्ट है ।

लेकिन एक ज्ञात विभाजक पर एक साधारण विभाजन के लिए (जैसे, डैश द्वारा विभाजन, या व्हाट्सएप द्वारा विभाजन), .str.split()विधि पर्याप्त 1 है । यह तारों के एक स्तंभ (श्रृंखला) पर काम करता है, और सूचियों का एक स्तंभ (श्रृंखला) लौटाता है:

>>> import pandas as pd
>>> df = pd.DataFrame({'AB': ['A1-B1', 'A2-B2']})
>>> df

      AB
0  A1-B1
1  A2-B2
>>> df['AB_split'] = df['AB'].str.split('-')
>>> df

      AB  AB_split
0  A1-B1  [A1, B1]
1  A2-B2  [A2, B2]

1: यदि आप अनिश्चित हैं कि पहले दो पैरामीटर .str.split()क्या हैं, तो मैं विधि के सादे पायथन संस्करण के लिए डॉक्स सुझाता हूं ।

लेकिन तुम कैसे जाते हो:

  • दो-तत्व सूचियों वाला स्तंभ

सेवा:

  • सूचियों के संबंधित तत्व वाले प्रत्येक दो कॉलम?

खैर, हमें .strएक कॉलम की विशेषता पर करीब से नज़र डालने की ज़रूरत है ।

यह एक जादुई वस्तु है जो स्तंभ में प्रत्येक तत्व को एक स्ट्रिंग के रूप में व्यवहार करने वाले तरीकों को इकट्ठा करने के लिए उपयोग किया जाता है, और फिर प्रत्येक तत्व में संबंधित विधि को यथासंभव प्रभावी रूप से लागू किया जाता है:

>>> upper_lower_df = pd.DataFrame({"U": ["A", "B", "C"]})
>>> upper_lower_df

   U
0  A
1  B
2  C
>>> upper_lower_df["L"] = upper_lower_df["U"].str.lower()
>>> upper_lower_df

   U  L
0  A  a
1  B  b
2  C  c

लेकिन इसके सूचकांक द्वारा स्ट्रिंग के प्रत्येक तत्व को प्राप्त करने के लिए एक "अनुक्रमणिका" इंटरफ़ेस भी है:

>>> df['AB'].str[0]

0    A
1    A
Name: AB, dtype: object

>>> df['AB'].str[1]

0    1
1    2
Name: AB, dtype: object

बेशक, यह अनुक्रमण इंटरफ़ेस .strवास्तव में परवाह नहीं करता है यदि अनुक्रमणिका का प्रत्येक तत्व वास्तव में एक स्ट्रिंग है, जब तक कि इसे अनुक्रमणित किया जा सकता है, इसलिए:

>>> df['AB'].str.split('-', 1).str[0]

0    A1
1    A2
Name: AB, dtype: object

>>> df['AB'].str.split('-', 1).str[1]

0    B1
1    B2
Name: AB, dtype: object

फिर, यह पायथन टपल के पुनरावृत्ति का लाभ उठाने का एक सरल मामला है

>>> df['A'], df['B'] = df['AB'].str.split('-', 1).str
>>> df

      AB  AB_split   A   B
0  A1-B1  [A1, B1]  A1  B1
1  A2-B2  [A2, B2]  A2  B2

बेशक, स्ट्रिंग्स के एक कॉलम को विभाजित करने से डेटाफ़्रेम प्राप्त करना इतना उपयोगी है कि यह .str.split()विधि आपके लिए expand=Trueपैरामीटर के लिए कर सकती है :

>>> df['AB'].str.split('-', 1, expand=True)

    0   1
0  A1  B1
1  A2  B2

इसलिए, जो हम करना चाहते थे उसे पूरा करने का एक और तरीका है:

>>> df = df[['AB']]
>>> df

      AB
0  A1-B1
1  A2-B2

>>> df.join(df['AB'].str.split('-', 1, expand=True).rename(columns={0:'A', 1:'B'}))

      AB   A   B
0  A1-B1  A1  B1
1  A2-B2  A2  B2

expand=Trueसंस्करण है, हालांकि लंबे समय तक, टपल खोल विधि पर एक विशिष्ट लाभ है। टपल अनपैकिंग अलग लंबाई के विभाजन के साथ अच्छी तरह से व्यवहार नहीं करता है:

>>> df = pd.DataFrame({'AB': ['A1-B1', 'A2-B2', 'A3-B3-C3']})
>>> df
         AB
0     A1-B1
1     A2-B2
2  A3-B3-C3
>>> df['A'], df['B'], df['C'] = df['AB'].str.split('-')
Traceback (most recent call last):
  [...]    
ValueError: Length of values does not match length of index
>>> 

लेकिन expand=Trueइसे Noneकॉलम में रखकर अच्छी तरह से संभालता है जिसके लिए पर्याप्त "विभाजन" नहीं हैं:

>>> df.join(
...     df['AB'].str.split('-', expand=True).rename(
...         columns={0:'A', 1:'B', 2:'C'}
...     )
... )
         AB   A   B     C
0     A1-B1  A1  B1  None
1     A2-B2  A2  B2  None
2  A3-B3-C3  A3  B3    C3

df ['A ’], df [] B’] = df [' AB ’]। str.split (’ ’, 1)।
हरिप्रसाद

@ हरिप्रसाद, यह विभाजन की अधिकतम संख्या है। मैंने विधि के पायथन संस्करण के लिए डॉक्स के लिए.split() एक लिंक जोड़ा है जो पहले दो मापदंडों को पंडों के डॉक्स से बेहतर बताता है।
सिंह रात्रि

5
पांडा 1.0.0 रिपोर्ट "FutureWarning: वर्णों पर स्तंभकार पुनरावृत्ति को भविष्य के रिलीज़ में हटा दिया जाएगा।"
फ्रैंक

1
यह पायथन 1.0.1 के तहत काम करता है। df.join(df['AB'].str.split('-', 1, expand=True).rename(columns={0:'A', 1:'B'}))
मार्टिन लॉब्रिंक

59

आप रेगेक्स पैटर्न का उपयोग करके अलग-अलग हिस्सों को बड़े करीने से निकाल सकते हैं :

In [11]: df.row.str.extract('(?P<fips>\d{5})((?P<state>[A-Z ]*$)|(?P<county>.*?), (?P<state_code>[A-Z]{2}$))')
Out[11]: 
    fips                    1           state           county state_code
0  00000        UNITED STATES   UNITED STATES              NaN        NaN
1  01000              ALABAMA         ALABAMA              NaN        NaN
2  01001   Autauga County, AL             NaN   Autauga County         AL
3  01003   Baldwin County, AL             NaN   Baldwin County         AL
4  01005   Barbour County, AL             NaN   Barbour County         AL

[5 rows x 5 columns]

कुछ हद तक रेगेक्स को समझाने के लिए:

(?P<fips>\d{5})
  • पांच अंकों ( \d) से मेल खाता है और उन्हें नाम देता है "fips"

अगला भाग:

((?P<state>[A-Z ]*$)|(?P<county>.*?), (?P<state_code>[A-Z]{2}$))

या तो ( |) दो चीजों में से एक:

(?P<state>[A-Z ]*$)
  • *पूंजी अक्षरों या स्थानों की किसी भी संख्या ( ) से मेल खाती है [A-Z ]और "state"स्ट्रिंग के अंत से पहले इसका नाम ( $),

या

(?P<county>.*?), (?P<state_code>[A-Z]{2}$))
  • .*फिर कुछ और ( ) से मेल खाता है
  • अल्पविराम और फिर एक स्थान
  • state_codeस्ट्रिंग के अंत से पहले दो अंकों से मेल खाता है ( $)।

उदाहरण में:
ध्यान दें कि पहली दो पंक्तियों ने "राज्य" (काउंटी और राज्य_कोड कॉलम में NaN को छोड़कर) को मारा, जबकि अंतिम तीन ने काउंटी, State_code (राज्य स्तंभ में NaN को छोड़कर) को मारा।


यह निश्चित रूप से सबसे अच्छा समाधान है, लेकिन यह बहुत व्यापक regex के साथ कुछ के लिए भारी हो सकता है। एक भाग 2 के रूप में और भाग 1 और पंक्ति कॉलम के साथ ऐसा क्यों नहीं है?
लिटिल बॉबी टेबल्स

2
@ जोश एक अच्छा बिंदु है, जबकि रेगेक्स के अलग-अलग हिस्सों को समझना "आसान" है, लंबे रेगेक्स जल्दी जटिल हो सकते हैं। मैंने भविष्य के पाठकों के लिए कुछ स्पष्टीकरण जोड़ा! (मुझे भी डॉक्स के लिए लिंक को अपडेट करना था जो (?P<label>...)वाक्यविन्यास को समझाता है ! मुझे नहीं पता कि मैं और अधिक जटिल रीगेक्स के लिए क्यों गया, स्पष्ट रूप से सरल एक हम्म्म्म काम कर सकता है
एंडी हेडन

1
ज्यादा फ्रेंडली लगती है। मुझे खुशी है कि आपने ऐसा किया क्योंकि मुझे समझने के लिए डॉक्स पर ध्यान दिया <group_name>। अब मुझे पता है कि यह मेरे कोड को बहुत सफल बनाता है।
लिटिल बॉबी टेबल


23

यदि आप एक नया डेटाफ़्रेम नहीं बनाना चाहते हैं, या यदि आपके डेटाफ़्रेम में आपके द्वारा विभाजित किए जाने की अपेक्षा अधिक कॉलम हैं, तो आप निम्न कार्य कर सकते हैं:

df["flips"], df["row_name"] = zip(*df["row"].str.split().tolist())
del df["row"]  

1
मुझे एक zip argument #1 must support iterationत्रुटि मिलती है , अजगर 2.7
एलन रुइन

20

आप नए स्तंभों को असाइन करने के लिए str.splitव्हाट्सएप (डिफ़ॉल्ट विभाजक) और पैरामीटर द्वारा उपयोग कर सकते हैं:expand=TrueDataFrame

df = pd.DataFrame({'row': ['00000 UNITED STATES', '01000 ALABAMA', 
                           '01001 Autauga County, AL', '01003 Baldwin County, AL', 
                           '01005 Barbour County, AL']})
print (df)
                        row
0       00000 UNITED STATES
1             01000 ALABAMA
2  01001 Autauga County, AL
3  01003 Baldwin County, AL
4  01005 Barbour County, AL



df[['a','b']] = df['row'].str.split(n=1, expand=True)
print (df)
                        row      a                   b
0       00000 UNITED STATES  00000       UNITED STATES
1             01000 ALABAMA  01000             ALABAMA
2  01001 Autauga County, AL  01001  Autauga County, AL
3  01003 Baldwin County, AL  01003  Baldwin County, AL
4  01005 Barbour County, AL  01005  Barbour County, AL

यदि आवश्यक हो तो संशोधन को मूल कॉलम के साथ हटा दें DataFrame.pop

df[['a','b']] = df.pop('row').str.split(n=1, expand=True)
print (df)
       a                   b
0  00000       UNITED STATES
1  01000             ALABAMA
2  01001  Autauga County, AL
3  01003  Baldwin County, AL
4  01005  Barbour County, AL

क्या समान है:

df[['a','b']] = df['row'].str.split(n=1, expand=True)
df = df.drop('row', axis=1)
print (df)

       a                   b
0  00000       UNITED STATES
1  01000             ALABAMA
2  01001  Autauga County, AL
3  01003  Baldwin County, AL
4  01005  Barbour County, AL

यदि त्रुटि मिलती है:

#remove n=1 for split by all whitespaces
df[['a','b']] = df['row'].str.split(expand=True)

ValueError: कॉलम कुंजी के समान ही होना चाहिए

आप जाँच कर सकते हैं और यह 4 कॉलम लौटाता है DataFrame, न केवल 2:

print (df['row'].str.split(expand=True))
       0        1        2     3
0  00000   UNITED   STATES  None
1  01000  ALABAMA     None  None
2  01001  Autauga  County,    AL
3  01003  Baldwin  County,    AL
4  01005  Barbour  County,    AL

फिर समाधान नया DataFrameहै join:

df = pd.DataFrame({'row': ['00000 UNITED STATES', '01000 ALABAMA', 
                           '01001 Autauga County, AL', '01003 Baldwin County, AL', 
                           '01005 Barbour County, AL'],
                    'a':range(5)})
print (df)
   a                       row
0  0       00000 UNITED STATES
1  1             01000 ALABAMA
2  2  01001 Autauga County, AL
3  3  01003 Baldwin County, AL
4  4  01005 Barbour County, AL

df = df.join(df['row'].str.split(expand=True))
print (df)

   a                       row      0        1        2     3
0  0       00000 UNITED STATES  00000   UNITED   STATES  None
1  1             01000 ALABAMA  01000  ALABAMA     None  None
2  2  01001 Autauga County, AL  01001  Autauga  County,    AL
3  3  01003 Baldwin County, AL  01003  Baldwin  County,    AL
4  4  01005 Barbour County, AL  01005  Barbour  County,    AL

मूल कॉलम को हटाने के साथ (यदि अन्य कॉलम भी हैं):

df = df.join(df.pop('row').str.split(expand=True))
print (df)
   a      0        1        2     3
0  0  00000   UNITED   STATES  None
1  1  01000  ALABAMA     None  None
2  2  01001  Autauga  County,    AL
3  3  01003  Baldwin  County,    AL
4  4  01005  Barbour  County,    AL   

8

यदि आप एक स्ट्रिंग को दो से अधिक स्तंभों में विभाजित करना चाहते हैं तो एक सीमांकक के आधार पर आप 'अधिकतम विभाजन' पैरामीटर को छोड़ सकते हैं।
आप उपयोग कर सकते हैं:

df['column_name'].str.split('/', expand=True)

यह स्वचालित रूप से आपके किसी भी प्रारंभिक स्ट्रिंग्स में शामिल फ़ील्ड की अधिकतम संख्या के रूप में कई कॉलम बनाएगा।


6

हैरानी की बात यह है कि मैंने इसे अभी तक नहीं देखा है। यदि आपको केवल दो विभाजन की आवश्यकता है, तो मैं अत्यधिक अनुशंसा करता हूं। । ।

Series.str.partition

partition विभाजक पर एक विभाजन करता है, और आम तौर पर काफी प्रदर्शन करने वाला होता है।

df['row'].str.partition(' ')[[0, 2]]

       0                   2
0  00000       UNITED STATES
1  01000             ALABAMA
2  01001  Autauga County, AL
3  01003  Baldwin County, AL
4  01005  Barbour County, AL

यदि आपको पंक्तियों का नाम बदलने की आवश्यकता है,

df['row'].str.partition(' ')[[0, 2]].rename({0: 'fips', 2: 'row'}, axis=1)

    fips                 row
0  00000       UNITED STATES
1  01000             ALABAMA
2  01001  Autauga County, AL
3  01003  Baldwin County, AL
4  01005  Barbour County, AL

यदि आपको मूल में वापस शामिल होना है, तो उपयोग करें joinया concat:

df.join(df['row'].str.partition(' ')[[0, 2]])

pd.concat([df, df['row'].str.partition(' ')[[0, 2]]], axis=1)

                        row      0                   2
0       00000 UNITED STATES  00000       UNITED STATES
1             01000 ALABAMA  01000             ALABAMA
2  01001 Autauga County, AL  01001  Autauga County, AL
3  01003 Baldwin County, AL  01003  Baldwin County, AL
4  01005 Barbour County, AL  01005  Barbour County, AL

0

मैं संबंधित पंडों की श्रृंखला (यानी मुझे जिन स्तंभों की आवश्यकता है) को निर्यात करने के लिए लागू करता है, स्तंभ सामग्री को कई श्रृंखलाओं में विभाजित करने के लिए लागू फ़ंक्शन का उपयोग करता है और फिर मौजूदा डेटाफ़्रेम में उत्पन्न कॉलम में शामिल होता है। बेशक, स्रोत स्तंभ को हटा दिया जाना चाहिए।

जैसे

 col1 = df["<col_name>"].apply(<function>)
 col2 = ...
 df = df.join(col1.to_frame(name="<name1>"))
 df = df.join(col2.toframe(name="<name2>"))
 df = df.drop(["<col_name>"], axis=1)

दो शब्दों को विभाजित करने के लिए स्ट्रिंग फ़ंक्शन कुछ इस तरह होना चाहिए:

lambda x: x.split(" ")[0] # for the first element
lambda x: x.split(" ")[-1] # for the last element

0

मैंने देखा कि किसी ने भी स्लाइस विधि का उपयोग नहीं किया था, इसलिए यहां मैंने अपने 2 सेंट लगाए।

df["<col_name>"].str.slice(stop=5)
df["<col_name>"].str.slice(start=6)

यह विधि दो नए कॉलम बनाएगी।


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