2016-05-15 157 views
3

如果我有一個數據幀,看起來像這樣:難據幀重塑Python的大熊貓

  DATE1 DATE2 DATE3 AMOUNT1 AMOUNT2 AMOUNT3 

1  1/1/15 5/22/14 7/12/13 5  6   3 
..   ..  ..  ..  ..  ..  .. 

,我想它的形式:

DATE AMOUNT 
1 1/1/15 5 
2 5/22/14 6 
3 7/12/13 3 
.. ..  .. 

什麼是最有效的代碼做這個?從我可以電話熔化或分組不會工作,因爲列名稱(DATE1,DATE2等)的差異。將「1」列,「2」列和「3」列分爲更小的數據框,重命名列和concat是最好的辦法嗎?還是有更好的方式來做到這一點,我失蹤了?

謝謝。

回答

7

你可以使用pd.lreshape

import pandas as pd 

df = pd.DataFrame([['1/1/15', '5/22/14', '7/12/13', 5, 6, 3]], 
        columns=['DATE1', 'DATE2', 'DATE3', 'AMOUNT1', 'AMOUNT2', 'AMOUNT3']) 

result = pd.lreshape(df, {'AMOUNT': ['AMOUNT1', 'AMOUNT2', 'AMOUNT3'], 
          'DATE': ['DATE1', 'DATE2', 'DATE3']}) 
print(result) 

產生

 DATE AMOUNT 
0 1/1/15  5 
1 5/22/14  6 
2 7/12/13  3 

的第二個參數是pd.lreshape鍵/值對的字典。每個鍵都是 所需列的名稱,每個值都是您希望合併到一列中的df 列的列表。

請參閱文檔字符串help(pd.lreshape),瞭解更多關於pd.lreshape的信息。


或者,你可以使用pd.melt所有列合併成一列,並使用str.extract到文本的部分從列名的數字部分分開。然後使用pivot,以獲得所期望的結果:

result = pd.melt(df) 
result[['variable', 'num']] = result['variable'].str.extract('(\D+)(\d+)', expand=True) 
result = result.pivot(index='num', columns='variable', values='value') 
print(result) 

產生

variable AMOUNT  DATE 
num      
1    5 1/1/15 
2    6 5/22/14 
3    3 7/12/13 
+4

TIL關於lreshape! – DSM

+0

謝謝。你能否在reshape()中解釋代碼? – Windstorm1981

+0

謝謝!非常清楚和有益的。有沒有很好的資源來找到這些「模糊」的方法?我不僅不熟悉lreshape() - 我甚至不知道在哪裏尋找這樣的方法。 – Windstorm1981

5

只需重塑.values

In [213]: 

print df 

    DATE1 DATE2 DATE3 AMOUNT1 AMOUNT2 AMOUNT3 
1 1/1/15 5/22/14 7/12/13  5  6  3 

In [214]: 

print pd.DataFrame(df.values.reshape((-1, 2), order='F'), 
        columns=['DATE', 'AMOUNT']) 

     DATE AMOUNT 
0 1/1/15  5 
1 5/22/14  6 
2 7/12/13  3 

假設每個行總是具有N日期和N量(這應該是情況?),我們可以將原始數據幀的值重新設置爲2列維數據幀。我們不知道最後會有多少行,這就是爲什麼我們可以在.reshape調用中使用(-1, 2)形狀,並讓.reshape確定需要多少行。 F意味着FORTRAN秩序,這是行優先,有效它是一樣的pd.DataFrame(df.values.reshape((-1, 2)).T

+0

謝謝。你能否解釋reshape()中的代碼? – Windstorm1981

+0

當然,請參閱編輯。 –

+0

謝謝。什麼是(-1,2)形狀?我在猜測2是列 - 如果是這樣的話,那麼對於行來說-1是什麼?對不起,如果這是一個愚蠢的問題 – Windstorm1981

4

這裏的另一種方法:你可以在列groupby

>>> grouped = df.groupby(df.columns.str[:-1], axis=1, sort=False) 
>>> pd.DataFrame.from_items((k, v.values.ravel()) for k,v in grouped) 
     DATE AMOUNT 
0 1/1/15  5 
1 5/22/14  6 
2 7/12/13  3 

僅除去最後一個字符是不一樣強大使用df.columns.str.extract("([A-Z]*)"或東西,但爲了演示它會工作。