2015-11-02 70 views
1

我有一張看起來像這樣的表。從CSV文件中讀取,所以沒有水平,沒有花哨的索引等如何用兩組變量彈出一個熊貓數據框

ID date1  amount1 date2  amount2 
x 15/1/2015 100  15/1/2016 80 

實際的文件我已經上升到date5和金額5 我怎樣才能將其轉換爲:

ID date  amount 
x 15/1/2015 100 
x 15/1/2016 80 

如果我只有一個變量,我會使用pandas.melt(),但有兩個變量,我真的不知道如何快速做到這一點。

我可以手動導出到內存中的sqlite3數據庫,並做一個聯合。在熊貓中進行聯合更麻煩,因爲與SQL不同,它需要所有字段名稱相同,因此在熊貓中,我必須創建一個臨時數據框並重命名所有字段:date1和amount1的數據幀,將字段的日期和金額,然後對所有其他事件做同樣的事情,只有這樣我才能做pandas.concat。

有什麼建議嗎?謝謝!

回答

1

如果我假設列總是重複,一個簡單的技巧提供了你想要的解決方案。

訣竅在於列出所有列的列表,然後根據需要循環遍歷主列表。它確實涉及每次循環運行時對pd.DataFrame()的調用。我現在有點時間想要找到避免這種情況的方法。但它的工作方式與您預期的相同,對於小文件,您不應該有任何問題(即運行時間)。

In [1]: columns = [['date1', 'amount1'], ['date2', 'amount2'], ...] 

In [2]: df_clean = pd.DataFrame(columns=['date', 'amount']) 
     for cols in columns: 
      df_clean = df_clean.append(pd.DataFrame(df.loc[:,cols].values, 
                columns=['date', 'amount']), 
             ignore_index=True) 
df_clean 
Out[2]:  date  amount 
     0 15/1/2015 100 
     1 15/1/2016 80 

對此的整潔的事情是,它只能在DataFrame上運行一次,選取它正在循環的列下的所有行。所以如果你有5個列對,在它下面有'n'行,循環將只運行5次。對於每次運行,它都會將列下的所有'n'行附加到乾淨的DataFrame中,爲您提供一致的結果。然後,您可以消除任何NaN值並按日期排序,或者對乾淨的DF執行任何您想要的操作。

您認爲,這是否創建了內存中的sqlite3數據庫?

3

這裏有一種方法:

>>> pandas.concat(
...  [pandas.melt(x, id_vars='ID', value_vars=x.columns[1::2].tolist(), value_name='date'), 
...  pandas.melt(x, value_vars=x.columns[2::2].tolist(), value_name='amount') 
...  ], 
...  axis=1 
...).drop('variable', axis=1) 
    ID  date amount 
0 x 15/1/2015  100 
1 x 15/1/2016  80 

的想法是做兩個熔體,每個組列,然後CONCAT他們。這假設這兩種列交替排列,以便columns[1::2]columns[2::2]正確選擇它們。如果沒有,你必須修改它的那一部分來選擇你想要的列。

您也可以做到這一點鮮爲人知lreshape

>>> pandas.lreshape(x, {'date': x.columns[1::2], 'amount': x.columns[2::2]}) 
    ID  date amount 
0 x 15/1/2015  100 
1 x 15/1/2016  80 

然而,lreshape是不是真的記錄,如果它應該使用目前還不清楚。

+0

非常有用,謝謝!是concat()與axis = 1相當於merge()? –

+0

@Pythonistaan​​onymous:我認爲'合併'比較靈活,允許不同類型的連接。 'concat'只是將多個DF彼此堆放在一起。 – BrenBarn

相關問題