Pandas는 목록 열을 여러 열로 분할합니다.


135

하나의 열이있는 pandas DataFrame이 있습니다.

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로 생성자를 lists만든 to_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
사소한주의 사항은 기존 데이터 프레임에서 사용하는 경우 인덱스를 재설정해야합니다. 그렇지 않으면 올바르게 할당되지 않습니다.
user1700890

1
@ user1700890-예, 또는 DataFrame 생성자에 인덱스 지정df2[['team1','team2']] = pd.DataFrame(df2.teams.values.tolist(), index= df2.index)
jezrael

1
@Catbuilts-예, 존재한다면 벡터화 솔루션을 피하는 것이 가장 좋습니다.
jezrael

1
@Catbuilts-예, 분명히. 벡터화는 일반적으로 루프가 없음을 의미하므로 적용, for, 목록 이해가 없습니다. 그러나 정확히 무엇이 필요한지에 따라 다릅니다. 어쩌면 또한 도움
jezrael

2
@Catbuilts Indeed apply()는 더 느릴 수 있지만 입력 문자열과 값이 원래 시리즈의 행에서 동일하지 않을 때 이동하는 방법입니다!
CheTesta

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
각 목록에 요소 수가 고르지 않은 경우 어떻게됩니까?
ikel 19.11.03

목록이 아닌 구분 된 문자열의 열을 분할하려는 경우 유사하게 수행 할 수 있습니다. df["teams"].str.split('<delim>', expand=True) 이미 DataFrame을 반환하므로 열 이름을 변경하는 것이 더 간단 할 것입니다.
AMC

26

이 솔루션 df2tolist()다음 을 사용하는 솔루션과 달리 DataFrame 의 인덱스를 유지 합니다 .

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
@Erfan 예,하지만 때로는 사용자가 작업에 1 초가 걸리는지 1ms가 걸리는지 신경 쓰지 않고 대신 가장 간단하고 읽기 쉬운 코드를 작성하는 데 가장 신경을 씁니다! 나는 가독성 / 단순성이 주관적이라는 것을 인정하지만, 내 요점은 단순히 모든 사용자에게 속도가 항상 우선 순위가 아니라는 것입니다.
Kevin Markham

1
또한이 apply방법이 대규모 데이터 세트에서 대규모 배열 (1000 개 이상의 항목)을 확장하는 데 더 안정적으로 작동 한다는 사실을 발견했습니다 . 이 tolist()방법은 데이터 세트가 500k 행을 초과했을 때 내 프로세스를 죽였습니다.
모리츠

2
이는 다양한 크기의 목록과 잘 작동하기 때문에 훌륭한 솔루션입니다.
dasilvadaniel

@KevinMarkham 그들은 가장 간단하고 가장 읽기 쉬운 코드를 작성하는 데 가장 관심 이 있습니다. pd.DataFrame(df["teams"].to_list(), columns=["team_1", "team_2"])정말 훨씬 더 복잡합니까?
AMC

15

제안 된 솔루션과 달리 구문 론적으로 더 간단한 방법이 있으므로 기억하기가 더 쉽습니다. 데이터 프레임 df에서 열이 '메타'라고 가정합니다.

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

1
오류가 발생했지만 str.split(). 이것은 훨씬 더 간단했고 목록에있는 항목의 수를 모르는 경우 이점이 있습니다.
otteheng

제안 된 솔루션과 달리 구문 론적으로 더 간단한 방법이 있으므로 기억하기가 더 쉽습니다. 정말? 이것은 몇 년 전에 게시 된 상위 답변과 거의 동일하기 때문입니다. 유일한 차이점은이 특정 질문과 관련이없는 부분입니다.
AMC

그것은 나에게 작동합니다 !!
EduardoUstarez

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

위의 솔루션은 nandataframe. 제 경우에는 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

이 유형은 길이가 다른 목록을 처리합니다. 이는 다른 많은 답변보다 개선되었지만 항목이 자체 열에 있지 않습니다.
Isaac

0

다음은 df.transform및 사용하는 또 다른 솔루션입니다 df.set_index.

>>> (df['teams']
       .transform([lambda x:x[0], lambda x:x[1]])
       .set_axis(['team1','team2'],
                  axis=1,
                  inplace=False)
    )

  team1 team2
0    SF   NYG
1    SF   NYG
2    SF   NYG
3    SF   NYG
4    SF   NYG
5    SF   NYG
6    SF   NYG
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.