290

1つの(文字列)列を持つデータフレームがあり、それを2つの(文字列)列に分割したいと思います。1つの列ヘッダーは' fips'、もう1つは'です。'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
4

11 に答える 11

627

TL;DR バージョン:

次の単純なケースの場合:

  • 区切り記号付きのテキスト列があり、2 つの列が必要です

最も簡単な解決策は次のとおりです。

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

文字列の分割数が不均一で、欠損値を置き換えexpand=Trueたい場合に使用する必要があります。None

どちらの場合も、.tolist()メソッドは必要ないことに注意してください。どちらでもないzip()

詳細に:

Andy Hayden のソリューション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: の最初の 2 つのパラメーターが何をするかわからない場合は、メソッドのプレーンな Python バージョンの.str.split()ドキュメントを参照することをお勧めします。

しかし、どうやって行くのですか:

  • 2 要素リストを含む列

に:

  • それぞれがリストのそれぞれの要素を含む2つの列?

.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

次に、イテラブルの Python tuple アンパックを利用して行うのは簡単なことです。

>>> 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

もちろん、文字列の列を分割して DataFrame を取得することは非常に便利であるため、.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
于 2016-09-06T22:52:23.940 に答える
170

もっと良い方法があるかもしれませんが、これは 1 つのアプローチです。

                            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 = ['fips','row'])
   fips                 row
0  00000       UNITED STATES
1  01000             ALABAMA
2  01001  Autauga County, AL
3  01003  Baldwin County, AL
4  01005  Barbour County, AL
于 2013-02-07T07:03:46.033 に答える
67

正規表現パターンを使用して、さまざまな部分をきれいに抽出できます。

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})
  • 5 桁の数字 ( \d) を照合して名前を付けます"fips"

次の部分:

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

|次の 2 つのいずれか ( ) を行います。

(?P<state>[A-Z ]*$)
  • *任意の数 ( ) の大文字またはスペース ( ) に一致し、文字列の末尾の前で[A-Z ]これに名前を付けます ( )。"state"$

また

(?P<county>.*?), (?P<state_code>[A-Z]{2}$))
  • それ以外に一致する ( .*) の場合
  • コンマとスペース
  • state_code文字列の末尾の2 桁前 ( $) に一致します。

例:
最初の 2 行は「州」にヒットし (county 列と state_code 列に NaN を残す)、最後の 3 行は郡、state_code にヒットする (州列に NaN を残す) ことに注意してください。

于 2014-01-23T00:20:07.503 に答える
51
df[['fips', 'row']] = df['row'].str.split(' ', n=1, expand=True)
于 2018-06-24T12:21:58.083 に答える
25

新しいデータフレームを作成したくない場合、またはデータフレームに分割したい列以外の列がある場合は、次のことができます。

df["flips"], df["row_name"] = zip(*df["row"].str.split().tolist())
del df["row"]  
于 2015-09-29T17:52:36.873 に答える
0

対応する pandas シリーズ (つまり、必要な列) をエクスポートし、apply関数を使用して列の内容を複数のシリーズに分割し、生成された列を既存の DataFrame に結合することを好みます。もちろん、ソース列は削除する必要があります。

例えば

 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)

2 つの単語の文字列関数を分割するには、次のようにする必要があります。

lambda x: x.split(" ")[0] # for the first element
lambda x: x.split(" ")[-1] # for the last element
于 2018-06-03T13:45:06.393 に答える