2017-03-08 25 views
2

私はちょうど同じような質問hereを配置して答えを得ましたが、DataFrameに新しい列を追加することで、問題が少し違うので、提示されたソリューションは失敗します。データ操作の例をpythonのワイドからロングまで

私はここから行ってみたい:

import pandas as pd 

df = pd.DataFrame({'ID': [1, 2], 
        'Value_2013': [100, 200], 
        'Value_2014': [245, 300], 
        'Value_2016': [200, float('NaN')]}) 

print(df) 

    ID Value_2013 Value_2014 Value_2016 
0 1   100   245  200.0 
1 2   200   300   NaN 

へ:

df_new = pd.DataFrame({'ID': [1, 1, 1, 2, 2], 
         'Year': [2013, 2014, 2016, 2013, 2014], 
         'Value': [100, 245, 200, 200, 300]}) 

print(df_new) 

    ID Value Year 
0 1 100 2013 
1 1 245 2014 
2 1 200 2016 
3 2 200 2013 
4 2 300 2014 

任意のアイデア私はこの挑戦に直面することができますか?

+0

? – Tzomas

+0

はい。しかし、溶融機能は上手く見えます!素晴らしい答えのすべてをありがとう! – Codutie

答えて

1

pandas.melt()メソッドが途中まで届きます。その後、ほんの少しの掃除です。

df = pd.melt(df, id_vars='ID', var_name='Year', value_name='Value') 
df['Year'] = df['Year'].map(lambda x: x.split('_')[1]) 
df = df.dropna().astype(int).sort_values(['ID', 'Year']).reset_index(drop=True) 
df = df.reindex_axis(['ID', 'Value', 'Year'], axis=1) 

print(df) 
    ID Value Year 
0 1 100 2013 
1 1 245 2014 
2 1 200 2016 
3 2 200 2013 
4 2 300 2014 
2

最初set_indexを追加必要があります。

df = df.set_index('ID') 
df.columns = df.columns.str.split('_', expand=True) 
df = df.stack().rename_axis(['ID','Year']).reset_index() 
df.Value = df.Value.astype(int) 
#if order of columns is important 
df = df.reindex_axis(['ID','Value','Year'], axis=1) 
print (df) 
    ID Value Year 
0 1 100 2013 
1 1 245 2014 
2 1 200 2016 
3 2 200 2013 
4 2 300 2014 
0

マルチインデックスを活用パンダ

import numpy as np 
import pandas as pd 
from collections import OrderedDict 

df = pd.DataFrame({'ID': [1, 2], 
        'Value_2013': [100, 200], 
        'Value_2014': [245, 300], 
        'Value_2016': [200, float('NaN')]}) 


# Set ID column as Index 
df = df.set_index('ID') 

# unstack all columns, swap the levels in the row index 
# and convert series to df 
df = df.unstack().swaplevel().to_frame().reset_index() 
# Rename columns as desired 
df.columns = ['ID', 'Year', 'Value'] 

# Transform the year values from Value_2013 --> 2013 and so on 
df['Year'] = df['Year'].apply(lambda x : x.split('_')[1]).astype(np.int) 

# Sort by ID 
df = df.sort_values(by='ID').reset_index(drop=True).dropna() 

print(df) 
    ID Year Value 
0 1 2013 100.0 
1 1 2014 245.0 
2 1 2016 200.0 
3 2 2013 200.0 
4 2 2014 300.0 
0

に別のオプションは)(pd.wide_to_longされます。確かにそれはあなたに正確に同じ出力を与えませんが、あなたは必要に応じてクリーンアップすることができます。

pd.wide_to_long(df, ['Value_',], i='', j='Year') 

      ID Value_ 
    Year    
NaN 2013 1  100 
    2013 2  200 
    2014 1  245 
    2014 2  300 
    2016 1  200 
    2016 2  NaN 
+0

ちょうど好奇心から:これはあなたのシステム上のコードの正確な出力ですか? 「Value_」列の「NaN」のために、私はdtypeが自動的に '' float''に変換されることを期待していました(整数 '' NaN''の欠如は私が嫌うものですPandasについてはとてもそうです)。それは使用しているバージョンで変更されていますか? – Schmuddi

+0

パンダス0.16.2とまったく同じです。 – Alexander

0

さらに別のsoution(2段階):元からのすべての列がValue_yearを呼び出すために起こっている

In [31]: x = df.set_index('ID').stack().astype(int).reset_index(name='Value') 

In [32]: x 
Out[32]: 
    ID  level_1 Value 
0 1 Value_2013 100 
1 1 Value_2014 245 
2 1 Value_2016 200 
3 2 Value_2013 200 
4 2 Value_2014 300 

In [33]: x = x.assign(Year=x.pop('level_1').str.extract(r'(\d{4})', expand=False)) 

In [34]: x 
Out[34]: 
    ID Value Year 
0 1 100 2013 
1 1 245 2014 
2 1 200 2016 
3 2 200 2013 
4 2 300 2014 
関連する問題