2017-03-08 25 views
2

我只是放在一個類似的問題here,並得到一個答案,但認識到,通過添加新列的數據幀的問題是有點不同的提出的解決方案失敗。數據處理例如從廣角到中長蟒蛇

我想從這裏去:

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

所有從原來的柱子會調用Value_year? – 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」是我討厭的東西關於熊貓)。你使用的版本有變化嗎? – Schmuddi

+0

這正是我用熊貓0.16.2所得到的結果。 – Alexander

0

另一個soution(兩個步驟):

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