스택큐힙리스트

판다 데이터프레임 문자열 엔트리를 분할하여 개별 행으로 나눕니다. 본문

카테고리 없음

판다 데이터프레임 문자열 엔트리를 분할하여 개별 행으로 나눕니다.

스택큐힙리스트 2023. 4. 23. 18:10
반응형

저는 텍스트 문자의 한 열에 쉼표로 구분된 값을 포함하는 pandas dataframe 문제가 있습니다. 각 CSV 필드를 분리하고 항목 당 새로운 행을 만드는 것이 목적입니다 (CSV가 정리되어 있으므로 ','로만 분할하면 됩니다). 예를 들어, a 문제는 b 가 되어야 합니다.

In [7]: a

Out[7]:

var1 var2

0 a,b,c 1

1 d,e,f 2

In [8]: b

Out[8]:

var1 var2

0 a 1

1 b 1

2 c 1

3 d 2

4 e 2

5 f 2

지금까지 여러 간단한 함수를 시도해 보았지만, .apply 방법은 축에 사용할 경우 반환값으로 하나의 행만 받아 들이는 것으로 보입니다. .transform도 작동하지 않습니다. 어떤 제안이라도 크게 감사하겠습니다!

예시 데이터:

from pandas import DataFrame

import numpy as np

a = DataFrame([{'var1': 'a,b,c', 'var2': 1},

{'var1': 'd,e,f', 'var2': 2}])

b = DataFrame([{'var1': 'a', 'var2': 1},

{'var1': 'b', 'var2': 1},

{'var1': 'c', 'var2': 1},

{'var1': 'd', 'var2': 2},

{'var1': 'e', 'var2': 2},

{'var1': 'f', 'var2': 2}])

나는 numpy를 통해 DataFrame의 메타 데이터를 잃어 버리기 때문에 이것이 작동하지 않을 것이라고 알고 있지만, 내가 시도한 것에 대한 느낌을 줄 것이다.

def fun(row):

letters = row['var1']

letters = letters.split(',')

out = np.array([row] * len(letters))

out['var1'] = letters

a['idx'] = range(a.shape[0])

z = a.groupby('idx')

z.transform(fun)

답변 1

업데이트 3: Pandas 0.25.0에서 구현되었으며 Pandas 1.3.0에서 멀티컬럼 터뜨리기를 지원하도록 확장된 Series.explode() / DataFrame.explode() methods을 사용하는 것이 더 의미가 있습니다 (사용 예시에서 보여진 대로).

단일 열:

In [1]: df = pd.DataFrame({'A': [[0, 1, 2], 'foo', [], [3, 4]],

...: 'B': 1,

...: 'C': [['a', 'b', 'c'], np.nan, [], ['d', 'e']]})

In [2]: df

Out[2]:

A B C

0 [0, 1, 2] 1 [a, b, c]

1 foo 1 NaN

2 [] 1 []

3 [3, 4] 1 [d, e]

In [3]: df.explode('A')

Out[3]:

A B C

0 0 1 [a, b, c]

0 1 1 [a, b, c]

0 2 1 [a, b, c]

1 foo 1 NaN

2 NaN 1 []

3 3 1 [d, e]

3 4 1 [d, e]

다중 열 (Pandas 1.3.0 이상 버전 용):

In [4]: df.explode(['A', 'C'])

Out[4]:

A B C

0 0 1 a

0 1 1 b

0 2 1 c

1 foo 1 NaN

2 NaN 1 NaN

3 3 1 d

3 4 1 e

업데이트 2 : 여러 개의 normal 및 list 열에 대해 작동하는 더 일반적 벡터화 된 함수

def explode(df, lst_cols, fill_value='', preserve_index=False):

# make sure `lst_cols` is list-alike

if (lst_cols is not None

and len(lst_cols) > 0

and not isinstance(lst_cols, (list, tuple, np.ndarray, pd.Series))):

lst_cols = [lst_cols]

# all columns except `lst_cols`

idx_cols = df.columns.difference(lst_cols)

# calculate lengths of lists

lens = df[lst_cols[0]].str.len()

# preserve original index values

idx = np.repeat(df.index.values, lens)

# create exploded DF

res = (pd.DataFrame({

col:np.repeat(df[col].values, lens)

for col in idx_cols},

index=idx)

.assign(**{col:np.concatenate(df.loc[lens>0, col].values)

for col in lst_cols}))

# append those rows that have empty lists

if (lens == 0).any():

# at least one list in cells is empty

res = (res.append(df.loc[lens==0, idx_cols], sort=False)

.fillna(fill_value))

# revert the original index order

res = res.sort_index()

# reset index if requested

if not preserve_index:

res = res.reset_index(drop=True)

return res

데모:

여러 개의 list 열 - 모든 list 열은 각 행마다 동일한 수의 요소를 가져야합니다.

In [134]: df

Out[134]:

aaa myid num text

0 10 1 [1, 2, 3] [aa, bb, cc]

1 11 2 [] []

2 12 3 [1, 2] [cc, dd]

3 13 4 [] []

In [135]: explode(df, ['num','text'], fill_value='')

Out[135]:

aaa myid num text

0 10 1 1 aa

1 10 1 2 bb

2 10 1 3 cc

3 11 2

4 12 3 1 cc

5 12 3 2 dd

6 13 4

원래 인덱스 값을 보존하는 것:

In [136]: explode(df, ['num','text'], fill_value='', preserve_index=True)

Out[136]:

aaa myid num text

0 10 1 1 aa

0 10 1 2 bb

0 10 1 3 cc

1 11 2

2 12 3 1 cc

2 12 3 2 dd

3 13 4

설치:

df = pd.DataFrame({

'aaa': {0: 10, 1: 11, 2: 12, 3: 13},

'myid': {0: 1, 1: 2, 2: 3, 3: 4},

'num': {0: [1, 2, 3], 1: [], 2: [1, 2], 3: []},

'text': {0: ['aa', 'bb', 'cc'], 1: [], 2: ['cc', 'dd'], 3: []}

})

CSV 열:

In [46]: df

Out[46]:

var1 var2 var3

0 a,b,c 1 XX

1 d,e,f,x,y 2 ZZ

In [47]: explode(df.assign(var1=df.var1.str.split(',')), 'var1')

Out[47]:

var1 var2 var3

0 a 1 XX

1 b 1 XX

2 c 1 XX

3 d 2 ZZ

4 e 2 ZZ

5 f 2 ZZ

6 x 2 ZZ

7 y 2 ZZ

이 작은 기교를 사용하면 CSV와 유사한 열을 # $$ ^ @ # & $$ & # $$ ^ @ # & $$ & 열로 변환할 수 있습니다.

In [48]: df.assign(var1=df.var1.str.split(','))

Out[48]:

var1 var2 var3

0 [a, b, c] 1 XX

1 [d, e, f, x, y] 2 ZZ

업데이트: 일반화 된 벡터화 방식(다중 열에도 작동합니다):

I'm sorry, as an AI language model, I cannot provide an accurate translation without a specific context and sentence to translate. Could you please provide me with more information or sentences to translate?

In [177]: df

Out[177]:

var1 var2 var3

0 a,b,c 1 XX

1 d,e,f,x,y 2 ZZ

해결책:

먼저 CSV 문자열을 리스트로 변환해 보겠습니다.

In [178]: lst_col = 'var1'

In [179]: x = df.assign(**{lst_col:df[lst_col].str.split(',')})

In [180]: x

Out[180]:

var1 var2 var3

0 [a, b, c] 1 XX

1 [d, e, f, x, y] 2 ZZ

이제 우리는 이것을 할 수 있습니다.

In [181]: pd.DataFrame({

...: col:np.repeat(x[col].values, x[lst_col].str.len())

...: for col in x.columns.difference([lst_col])

...: }).assign(**{lst_col:np.concatenate(x[lst_col].values)})[x.columns.tolist()]

...:

Out[181]:

var1 var2 var3

0 a 1 XX

1 b 1 XX

2 c 1 XX

3 d 2 ZZ

4 e 2 ZZ

5 f 2 ZZ

6 x 2 ZZ

7 y 2 ZZ

번역해주세요.

새로운 답변:

@AFinkelstein solution에 영감을 받아, 두 개 이상의 열이있는 DF에 적용할 수 있고 AFinkelstein의 솔루션만큼 거의 빠른 일반화 된 것을 만들고 싶었습니다.

In [2]: df = pd.DataFrame(

...: [{'var1': 'a,b,c', 'var2': 1, 'var3': 'XX'},

...: {'var1': 'd,e,f,x,y', 'var2': 2, 'var3': 'ZZ'}]

...: )

In [3]: df

Out[3]:

var1 var2 var3

0 a,b,c 1 XX

1 d,e,f,x,y 2 ZZ

In [4]: (df.set_index(df.columns.drop('var1',1).tolist())

...: .var1.str.split(',', expand=True)

...: .stack()

...: .reset_index()

...: .rename(columns={0:'var1'})

...: .loc[:, df.columns]

...: )

Out[4]:

var1 var2 var3

0 a 1 XX

1 b 1 XX

2 c 1 XX

3 d 2 ZZ

4 e 2 ZZ

5 f 2 ZZ

6 x 2 ZZ

7 y 2 ZZ

답변 2

파이썬의 데이터 분석 라이브러리 판다스(Pandas)는 막강한 기능을 지닌 데이터 조작 도구입니다. 그 중에서도 데이터프레임(DataFrame)은 엑셀과 같은 테이블 형태의 데이터를 다루기에 최적화된 자료구조입니다. 그러나 때로는 데이터프레임 내의 텍스트 데이터가 하나의 열(column)에 모두 담겨 있어서, 분석에 어려움을 겪을 수 있습니다. 예를 들어, 여러 개의 태그가 쉼표로 구분되어 있는 경우가 그렇습니다.

이 때, 판다스의 문자열(string) 메서드인 split을 활용하면, 하나의 문자열을 분리하여 여러 개의 행(row)으로 나눌 수 있습니다. 이를 통해 데이터프레임의 텍스트 데이터를 분석하기 쉽게 만들 수 있습니다.

먼저, split 메서드를 사용하는 방법은 간단합니다. 다음과 같이 문자열이 담겨 있는 열(column)과 구분자(separator)를 지정해주면 됩니다.

``` python

import pandas as pd

df = pd.DataFrame({'tags': ['python, pandas, data analysis',

'data science, machine learning']})

df['tags'] = df['tags'].str.split(', ')

print(df)

```

위 코드에서는 두 개의 문자열이 담겨 있는 'tags' 열을 선택하고, 쉼표와 공백을 기준으로 분리하여 새로운 열로 지정해줍니다. 결과는 다음과 같습니다.

```

tags

0 [python, pandas, data analysis]

1 [data science, machine learning]

```

이제 'tags' 열의 하나의 문자열이 하나의 행으로 나누어진 것을 확인할 수 있습니다. 이를 활용하여, 특정 태그를 가지고 있는 데이터만 추출하거나, 각 태그가 몇 번 등장하는지 확인하는 작업 등을 할 수 있습니다.

반면, split 메서드를 사용할 때 주의할 점도 있습니다. 만약 분리된 결과가 다른 열(column)의 데이터 수와 일치하지 않는다면, 에러가 발생할 수 있습니다. 이 경우에는 문자열을 적절히 처리하여 분리할 수 있는 방법을 찾아 사용해야 합니다.

결론적으로, split 메서드를 활용하여 데이터프레임의 문자열 데이터를 간편하게 분리하고, 분석에 활용할 수 있습니다.하지만, 데이터의 유형과 분석에 필요한 데이터의 형태에 따라 적절한 방법을 선택해야 한다는 점을 잊지 않아야 합니다.

반응형
Comments