2017-09-03 3 views
1

여러 개의 다중 값 열이있는 큰 팬더 데이터 프레임이 있습니다. 이 열은 이름에 "/"가 있으며이 열의 값은 "/"로 구분됩니다. 아래는 이러한 데이터 프레임의 대표적인 예입니다.팬더 : 이름의 구분자를 기반으로하는 다중 값 열 분할

 Name North/South East/West No1/No2/No3 
0  ABC   0/1   0/0  10/3/6 
1  XYZ   1/0   0/1   4/5/6 
2  PQR   1/0   0/1   3/6/6 

열을 나누고 싶습니다. 간단한 방법은 새 열을 만든 다음 인덱스의 길이를 따라 반복하여 각 요소를 따라 분할 된 문자열로 채 웁니다. 하지만 모든 다중 값 열에 대해 하드 코딩해야합니다.

더 일반적인 방법이 있습니까? 아마도 df.columns를 통해 스캔 한 다음 요소에 "/"가 포함되어 있으면 다른 함수를 실행하여 해당 열을 분할 할 수 있습니까? 위의 데이터 프레임에서 원하는 출력은 다음과 같습니다.

 Name North South East West No1 No2 No3 
0  ABC  0  1  0  0 10 3 6 
1  XYZ  1  0  0  1 4 5 6 
2  PQR  1  0  0  1 3 6 6 

답변

0
#get columns not contains/and set index 
cols = df.columns[~df.columns.str.contains('/')].tolist() 
df = df.set_index(cols) 
print (df) 
    North/South East/West No1/No2/No3 
Name           
ABC   0/1  0/0  10/3/6 
XYZ   1/0  0/1  4/5/6 
PQR   1/0  0/1  3/6/6 

#create new columns names 
c = df.columns.to_series().str.split('/', expand=True).stack().values.tolist() 
print (c) 
['North', 'South', 'East', 'West', 'No1', 'No2', 'No3'] 

#list comprehension with split to df and concat output 
df = pd.concat([df[x].str.split('/', expand=True) for x in df], axis=1) 
print (df) 
     0 1 0 1 0 1 2 
Name      
ABC 0 1 0 0 10 3 6 
XYZ 1 0 0 1 4 5 6 
PQR 1 0 0 1 3 6 6 

#assign new columns names 
df.columns = c 
df = df.reset_index() 
print (df) 
    Name North South East West No1 No2 No3 
0 ABC  0  1 0 0 10 3 6 
1 XYZ  1  0 0 1 4 5 6 
2 PQR  1  0 0 1 3 6 6 

타이밍 :

df = pd.concat([df]*1000).reset_index(drop=True) 
print (df) 

def f(df): 
    return pd.concat([s.str.split('/').apply(pd.Series, index=c.split('/')) for c, s in df.set_index('Name').iteritems()], axis=1).reset_index() 
print (f(df)) 

def f1(df): 
    cols = df.columns[~df.columns.str.contains('/')].tolist() 
    df = df.set_index(cols) 
    c = df.columns.to_series().str.split('/', expand=True).stack().values.tolist() 
    df = pd.concat([df[x].str.split('/', expand=True) for x in df], axis=1) 
    df.columns = c 
    return df.reset_index() 
print (f1(df)) 

In [142]: %timeit (f(df)) 
1 loop, best of 3: 2.6 s per loop 

In [143]: %timeit (f1(df)) 
10 loops, best of 3: 27.5 ms per loop 
+0

감사합니다. 나는 그것을 실행하는 몇 가지 문제가 있습니다. df = df.set_index (cols)로 df를 변경했다고 생각합니다. 그래서 c = df.columns.to_series(). str.split ('/', expand = True) .stack(). values를 실행하면 오류가 발생합니다. 해결책을 다시 확인할 수 있습니까? – Spinor8

+0

어떤 종류의 오류가 있습니까? – jezrael

+0

괜찮습니다. 내 부분에서 실수. 다시 한번 감사드립니다. – Spinor8

1

여기에 한 가지 방법을 솔루션에 대한

In [1417]: pd.concat([s.str.split('/').apply(pd.Series, index=c.split('/')) 
        for c, s in df.set_index('Name').iteritems()], 
        axis=1).reset_index() 
Out[1417]: 
    Name North South East West No1 No2 No3 
0 ABC  0  1 0 0 10 3 6 
1 XYZ  1  0 0 1 4 5 6 
2 PQR  1  0 0 1 3 6 6 
+0

해결책 주셔서 감사합니다. 그것은 장난감 예를 들어 작동하지만 Jezrael 's는 더 일반적입니다. – Spinor8