열을 두 열로 나누는 방법은 무엇입니까?


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
팬더에 데이터를 어떻게로드 했습니까? read_table()또는 read_fwf()
zach

답변:


140

더 좋은 방법이있을 수 있지만 여기에는 한 가지 방법이 있습니다.

                            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에서 다시 인덱스됩니다 (특정 경우 중요하지 않음).
Crashthatch

10
@Crashthatch-다시 추가 index = df.index하면됩니다.
root

하나의 셀을 분할 할 수 없으면 어떻게합니까?
Nisba

@Nisba : 셀을 분할 할 수없는 경우 (예 : 문자열에이 공간이없는 경우) 여전히 작동하지만 분할의 한 부분은 비어 있습니다. 열에 유형이 혼합되어 있고 숫자 유형을 포함하는 하나 이상의 셀이있는 경우 다른 상황이 발생합니다. 그런 다음 split메소드는 NaN을 리턴하고 tolist메소드는이 값을 (NaN)으로 리턴하므로 결과적 ValueError으로이 문제를 극복하기 위해 분할 전에 문자열 유형으로 캐스트 할 수 있습니다. 본인이 직접 시도해 보는 것이 좋습니다. 최고의 학습 방법입니다 :-)
Nerxis

@techkuz : 당신은 당신이 확신 dfrow열 머리글을? 일종의 DataFrame 속성이라고 생각할 수도 있지만 이것이 열 이름이라는 것은 분명합니다. 열 머리글을 만들고 정의하는 방법은 사용자에게 달려 있으므로 다른 머리글을 사용하는 경우 (예 :) 사용하십시오 df.my_column_name.split(...).
Nerxis

392

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().

상세히:

Andy Hayden의 솔루션 은이 str.extract()방법 의 성능을 가장 잘 보여줍니다 .

그러나 알려진 구분 기호에 대한 간단한 분할 (예 : 대시로 나누기 또는 공백으로 나누기)의 경우이 .str.split()방법으로 충분합니다 1 . 문자열의 열 (Series)에서 작동하며 목록의 열 (Series)을 리턴합니다.

>>> 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 : 처음 두 매개 변수가 무엇인지 확실하지 않은 경우 일반 Python 버전의 메서드에.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

그런 다음 파이썬 튜플의 iterables 압축 풀기를 활용하는 간단한 문제입니다.

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

df [ 'A'], df [ 'B'] = df [ 'AB']. str.split ( '', 1) .str split ( '', 1)에서 '1'의 의미는 무엇입니까?
Hariprasad

@Hariprasad, 최대 분할 수입니다. Pandas 문서보다 처음 두 매개 변수를 더 잘 설명하는 메소드 의 Python 버전 문서에 대한.split() 링크를 추가했습니다 .
LeoRochael

5
pandas 1.0.0은 "FutureWarning : 문자에 대한 열 반복은 향후 릴리스에서 더 이상 사용되지 않을 것"이라고보고합니다.
Frank

1
이것은 Python 1.0.1에서 작동합니다. df.join(df['AB'].str.split('-', 1, expand=True).rename(columns={0:'A', 1:'B'}))
Martien Lubberink

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문자열 끝 ( $) 앞 의 두 자리 숫자와 일치합니다 .

예제에서 :
처음 두 행은 "state"(county 및 state_code 열에 NaN을 남기고)를, 마지막 3 개 행은 state_code (state 열에 NaN을 남겨)를 누르십시오.


이것은 확실히 최고의 솔루션이지만 매우 광범위한 정규 표현식을 사용하는 사람들에게는 다소 압도적 일 수 있습니다. 왜 파트 2로 사용하고 fips와 행 열만으로 파트 1을 사용하지 않습니까?
리틀 바비 테이블

2
@josh는 좋은 점입니다. 정규 표현식의 개별 부분은 이해하기 쉽지만 긴 정규 표현식은 빠르게 복잡해질 수 있습니다. 장래 독자들을위한 설명을 추가했습니다! (또한 (?P<label>...)구문 을 설명하는 문서에 대한 링크를 업데이트해야했습니다 ! 더 복잡한 정규 표현식을 선택한 이유를 모르겠습니다. 단순하게 간단하게 사용할 수 있습니다.
Andy Hayden

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=True에 대한 DataFrame새 열을 할당과 :

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 : 열은 키와 길이가 같아야합니다

당신은 확인 할 수 있으며 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

구분자를 기준으로 문자열을 두 개 이상의 열로 분할하려는 경우 'maximum splits'매개 변수를 생략 할 수 있습니다.
당신이 사용할 수있는:

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

적용 기능을 사용하여 해당 팬더 시리즈 (필요한 열)를 내보내 열 내용을 여러 시리즈로 분할 한 다음 생성 된 열을 기존 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)

두 단어를 분리하려면 문자열 기능은 다음과 같아야합니다.

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.