2016-10-04 16 views
2

パンダのデータフレームに複数の行に行を爆発:私は次のヘッダーを持つデータフレーム持って

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 for now – 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 

EDIT:

lreshapeは文書化されていませんが、今後削除される可能性があります(with pd.wide_to_long too)。

考えられる解決策は3つの機能すべてを1つにマージすることです - おそらくmeltですが、今は実装されていません。たぶん新しいバージョンのパンダで。その後、私の答えは更新されます。

関連する問題