কীভাবে একটি কলাম দুটি কলামে বিভক্ত করবেন?


196

আমার একটি কলাম সহ একটি ডেটা ফ্রেম রয়েছে এবং আমি এটিকে দুটি কলামে বিভক্ত করতে চাই, যার একটি কলাম শিরোনাম ' 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

উত্তর:


135

আরও ভাল উপায় হতে পারে, তবে এটি এখানে একটি পদ্ধতির:

                            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পদ্ধতিটি এই মানটি (এনএএনএন) হিসাবে ফিরিয়ে দেবে যার ফলস্বরূপ ValueError(এই সমস্যাটি কাটিয়ে উঠতে আপনি বিভক্ত হওয়ার আগে স্ট্রিং টাইপে এটি ফেলে দিতে পারেন)। আমি আপনাকে এটি নিজেরাই চেষ্টা করার পরামর্শ দিচ্ছি এটি শেখার সর্বোত্তম উপায় :-)
নের্কসিস

@techkuz: আপনি নিশ্চিত করুন যে আপনার পেরেছেন dfহয়েছে rowকলাম শিরোনাম? আপনি মনে করতে পারেন এটি কোনও প্রকারের ডেটা ফ্রেম বৈশিষ্ট্যটি কিন্তু এটি সম্পূর্ণরূপে পরিষ্কার যে এটি কলামটির নাম। আপনি কীভাবে আপনার কলামের শিরোনামগুলি তৈরি এবং সংজ্ঞায়িত করেন এটি আপনার উপর নির্ভর করে যদি আপনি এটির বিভিন্ন ব্যবহার করেন তবে (যেমন df.my_column_name.split(...))।
Nerxis

386

টিএল; ডিআর সংস্করণ:

এর সাধারণ ক্ষেত্রে:

  • আমার একটি ডিলিমিটার সহ একটি পাঠ্য কলাম রয়েছে এবং আমি দুটি কলাম চাই

সহজ সমাধানটি হ'ল:

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

অথবা আপনি বিভাজনের প্রতিটি প্রবেশের জন্য স্বয়ংক্রিয়ভাবে এক কলাম সহ একটি ডেটা ফ্রেম তৈরি করতে পারেন:

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একটি কলামের বৈশিষ্ট্যটি খুব কাছ থেকে নেওয়া উচিত ।

এটি একটি icalন্দ্রজালিক অবজেক্ট যা কলামে প্রতিটি উপাদানকে স্ট্রিং হিসাবে আচরণ করে এমন পদ্ধতিগুলি সংগ্রহ করতে ব্যবহৃত হয় এবং তারপরে প্রতিটি উপাদানটিতে যথাসম্ভব দক্ষতার সাথে সম্পর্কিত পদ্ধতি প্রয়োগ করে:

>>> 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সংস্করণ, যদিও আর tuple unpacking পদ্ধতি উপর একটি স্বতন্ত্র সুবিধা আছে। টুপল আনপ্যাকিং বিভিন্ন দৈর্ঘ্যের স্প্লিটগুলির সাথে ভালভাবে মোকাবেলা করে না:

>>> 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) .১ বিভক্ত হয়ে '1' এর অর্থ কী ('', 1)?
হরিপ্রসাদ

@ হরিপ্রসাদ, এটি বিভাজনের সর্বাধিক সংখ্যা। আমি পদ্ধতির পাইথন সংস্করণে ডক্সে.split() একটি লিঙ্ক যুক্ত করেছি যা পান্ডাস ডক্সের চেয়ে প্রথম দুটি পরামিতি আরও ভাল ব্যাখ্যা করে।
লিওরোচেল

5
পান্ডাস 1.0.0 প্রতিবেদন করেছে "ফিউচার ওয়ার্নিং: অক্ষরের উপরে কলামার পুনরাবৃত্তি ভবিষ্যতের প্রকাশগুলিতে হ্রাস করা হবে।"
ফ্রাঙ্ক

1
এটি পাইথন 1.0.1 এর অধীনে কাজ করে। df.join(df['AB'].str.split('-', 1, expand=True).rename(columns={0:'A', 1:'B'}))
মার্টিয়েন লুবারিংক

59

আপনি করতে পারেন নিষ্কর্ষ আউট বেশ সুন্দরভাবে একটি Regex প্যাটার্ন ব্যবহার করে বিভিন্ন অংশ:

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স্ট্রিং ( $) এর শেষ হওয়ার আগে দুটি অঙ্কের সাথে মেলে ।

উদাহরণস্বরূপ:
নোট করুন যে প্রথম দুটি সারি "স্টেট" (কাউন্টি এবং state_code কলামগুলিতে NaN রেখে) হিট করেছে, যখন শেষ তিনটি কাউন্টি, state_code (রাজ্য কলামে NaN রেখে) hit


এটি অবশ্যই সেরা সমাধান তবে এটি খুব বিস্তৃত রেগেক্সের সাথে কারও কাছে কিছুটা অভিভূত হতে পারে। কেন এটি একটি অংশ 2 হিসাবে না এবং কেবল 1 টিপ এবং সারি কলামগুলির সাথে অংশ 1 রয়েছে?
লিটল ববি টেবিলগুলি

2
@ জোশ এটি একটি ভাল পয়েন্ট, যদিও রেজেক্সের পৃথক অংশগুলি বোঝার জন্য "সহজ", দীর্ঘ রেজেক্স দ্রুত জটিল হতে পারে। আমি ভবিষ্যতের পাঠকদের জন্য কিছু ব্যাখ্যা যুক্ত করেছি! (আমাকে ডক্সের লিঙ্কটিও আপডেট করতে হয়েছিল যা (?P<label>...)সিনট্যাক্সের ব্যাখ্যা দিয়েছিল ! আমি কেন জানি না কেন আমি আরও জটিল রেজেক্সের জন্য গেলাম, স্পষ্টতই সরল ব্যক্তি হুঁ মিম কাজ করতে পারে
অ্যান্ডি হেডেন

1
দেখতে অনেক বন্ধুবান্ধব লাগছে। আমি আনন্দিত আপনি এটি করেছেন কারণ এটি আমাকে বুঝতে ডক্সকে দেখেছিল <group_name>। এখন আমি জানি এটি আমার কোডটিকে খুব সংহত করে।
লিটল ববি টেবিল


22

আপনি যদি কোনও নতুন ডেটাফ্রেম তৈরি করতে না চান, বা আপনার ডেটাফ্রেমে যদি আপনি বিভাজন করতে চান কেবল তার চেয়ে বেশি কলাম থাকে তবে আপনি এটি করতে পারেন:

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

1
আমি একটি zip argument #1 must support iterationত্রুটি পাই , অজগর ২.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)

মান মূল্য: কলামগুলি কী হিসাবে একই দৈর্ঘ্য হতে হবে

আপনি যাচাই করতে পারেন এবং এটি DataFrame2 টি নয়, 4 টি কলাম ফেরত দেয় :

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)

এই পদ্ধতিটি দুটি নতুন কলাম তৈরি করবে।


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.