2016-10-04 6 views
2

팬더 dataframe에서 여러 행에 대한 행을 폭발 :나는 다음과 같은 헤더와 dataframe이

id, type1, ..., type10, location1, ..., location10 

을 다음과 같이 나는 그것을 변환 할 :

id, type, location 

나는 사용하여이 작업을 수행하기 위해 관리 루프에 내장되어 있지만 매우 느립니다.

new_format_columns = ['ID', 'type', 'location'] 
new_format_dataframe = pd.DataFrame(columns=new_format_columns) 



print(data.head()) 
new_index = 0 
for index, row in data.iterrows(): 
     ID = row["ID"] 

     for i in range(1,11): 
       if row["type"+str(i)] == np.nan: 
         continue 
       else: 
         new_row = pd.Series([ID, row["type"+str(i)], row["location"+str(i)]]) 
         new_format_dataframe.loc[new_index] = new_row.values 
         new_index += 1 

기본 팬더 기능을 사용하여 개선 할 사항이 있습니까?

+0

데이터 세트의 크기는 얼마입니까? – MMF

+0

@MMF 지금은 몇 GB – MedAli

답변

4

당신은 lreshape 사용할 수 있습니다

types = [col for col in df.columns if col.startswith('type')] 
location = [col for col in df.columns if col.startswith('location')] 

print(pd.lreshape(df, {'Type':types, 'Location':location}, dropna=False)) 

샘플 :

import pandas as pd 

df = pd.DataFrame({ 
'type1': {0: 1, 1: 4}, 
'id': {0: 'a', 1: 'a'}, 
'type10': {0: 1, 1: 8}, 
'location1': {0: 2, 1: 9}, 
'location10': {0: 5, 1: 7}}) 

print (df) 
    id location1 location10 type1 type10 
0 a   2   5  1  1 
1 a   9   7  4  8 

types = [col for col in df.columns if col.startswith('type')] 
location = [col for col in df.columns if col.startswith('location')] 

print(pd.lreshape(df, {'Type':types, 'Location':location}, dropna=False)) 
    id Location Type 
0 a   2  1 
1 a   9  4 
2 a   5  1 
3 a   7  8 

더블 melt 또 다른 솔루션 :

print (pd.concat([pd.melt(df, id_vars='id', value_vars=types, value_name='type'), 
        pd.melt(df, value_vars=location, value_name='Location')], axis=1) 
     .drop('variable', axis=1)) 

    id type Location 
0 a  1   2 
1 a  4   9 
2 a  1   5 
3 a  8   7 

편집 :

lreshape은 문서화되지 않았지만 향후에 삭제 될 수 있습니다 (with pd.wide_to_long too).

가능한 모든 솔루션은 3 가지 기능을 모두 하나로 합치는 것이지만 어쩌면 melt이지만 구현되지 않았습니다. 어쩌면 판다의 새로운 버전에서. 그럼 내 대답이 업데이트 될거야.