2015-03-30 50 views
4

考慮下面的數據幀「前進填充」:有效地重新索引一個水平的多指標數據幀

      value 
item_uid created_at   

0S0099v8iI 2015-03-25 10652.79 
0F01ddgkRa 2015-03-25 1414.71 
0F02BZeTr6 2015-03-20 51505.22 
      2015-03-23 51837.97 
      2015-03-24 51578.63 
      2015-03-25  NaN 
      2015-03-26  NaN 
      2015-03-27 50893.42 
0F02BcIzNo 2015-03-17 1230.00 
      2015-03-23 1130.00 
0F02F4gAMs 2015-03-25 1855.96 
0F02Vwd6Ou 2015-03-19 5709.33 
0F04OlAs0R 2015-03-18 321.44 
0F05GInfPa 2015-03-16 664.68 
0F05PQARFJ 2015-03-18 1074.31 
      2015-03-26 1098.31 
0F06LFhBCK 2015-03-18 211.49 
0F06ryso80 2015-03-16  13.73 
      2015-03-20  12.00 
0F07gg7Oth 2015-03-19 2325.70 

我需要採樣兩個日期start_dateend_date之間的全面數據幀上之間的每一個日期他們宣傳最後看到的價值。採樣應在每個item_uid獨立/分開進行。

例如,如果我們的0F02BZeTr62015-03-202015-03-29之間來樣,我們應該得到:

0F02BZeTr6 2015-03-20 51505.22 
      2015-03-21 51505.22 
      2015-03-22 51505.22 
      2015-03-23 51837.97 
      2015-03-24 51578.63 
      2015-03-25 51578.63 
      2015-03-26 51578.63 
      2015-03-27 50893.42 
      2015-03-28 50893.42 
      2015-03-29 50893.42 

注意,我向前數據幀都填充NaN缺少的條目

This other question解決了類似的問題,但只有一個組(即一個級別)。這個問題改爲詢問如何在每個組內(item_uid)單獨進行。雖然我可以拆分輸入數據幀並遍歷每個組(每個item_uid),然後將結果拼接在一起,但我想知道是否有更有效的方法。

當我做了以下(見this PR):

dates   = pd.date_range(start=start_date, end=end_date)  
df.groupby(level='itemuid').apply(lambda x: x.reindex(dates, method='ffill')) 

我得到:

TypeError: Fill method not supported if level passed 

回答

3

你有幾個選項,最簡單的IMO是簡單地拆散的第一級,然後ffill。我想,這使得它更瞭解發生了什麼事情比GROUPBY /重採樣解決方案更清晰的(我懷疑它也將更快,這取決於數據):

In [11]: df1['value'].unstack(0) 
Out[11]: 
item_uid 0F01ddgkRa 0F02BZeTr6 0F02BcIzNo 0F02F4gAMs 0F02Vwd6Ou 0F04OlAs0R 0F05GInfPa 0F05PQARFJ 0F06LFhBCK 0F06ryso80 0F07gg7Oth 0S0099v8iI 
created_at 
2015-03-16   NaN   NaN   NaN   NaN   NaN   NaN  664.68   NaN   NaN  13.73   NaN   NaN 
2015-03-17   NaN   NaN  1230   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN 
2015-03-18   NaN   NaN   NaN   NaN   NaN  321.44   NaN  1074.31  211.49   NaN   NaN   NaN 
2015-03-19   NaN   NaN   NaN   NaN  5709.33   NaN   NaN   NaN   NaN   NaN  2325.7   NaN 
2015-03-20   NaN 51505.22   NaN   NaN   NaN   NaN   NaN   NaN   NaN  12.00   NaN   NaN 
2015-03-23   NaN 51837.97  1130   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN 
2015-03-24   NaN 51578.63   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN 
2015-03-25  1414.71   NaN   NaN  1855.96   NaN   NaN   NaN   NaN   NaN   NaN   NaN 10652.79 
2015-03-26   NaN   NaN   NaN   NaN   NaN   NaN   NaN  1098.31   NaN   NaN   NaN   NaN 
2015-03-27   NaN 50893.42   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN 

如果你丟失了一些約會,你必須重新索引(假設開始和結束都存在,否則,你可以這樣做手工,例如用pd.date_range):

In [12]: df1['value'].unstack(0).asfreq('D') 
Out[12]: 
item_uid 0F01ddgkRa 0F02BZeTr6 0F02BcIzNo 0F02F4gAMs 0F02Vwd6Ou 0F04OlAs0R 0F05GInfPa 0F05PQARFJ 0F06LFhBCK 0F06ryso80 0F07gg7Oth 0S0099v8iI 
2015-03-16   NaN   NaN   NaN   NaN   NaN   NaN  664.68   NaN   NaN  13.73   NaN   NaN 
2015-03-17   NaN   NaN  1230   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN 
2015-03-18   NaN   NaN   NaN   NaN   NaN  321.44   NaN  1074.31  211.49   NaN   NaN   NaN 
2015-03-19   NaN   NaN   NaN   NaN  5709.33   NaN   NaN   NaN   NaN   NaN  2325.7   NaN 
2015-03-20   NaN 51505.22   NaN   NaN   NaN   NaN   NaN   NaN   NaN  12.00   NaN   NaN 
2015-03-21   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN 
2015-03-22   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN 
2015-03-23   NaN 51837.97  1130   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN 
2015-03-24   NaN 51578.63   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN 
2015-03-25  1414.71   NaN   NaN  1855.96   NaN   NaN   NaN   NaN   NaN   NaN   NaN 10652.79 
2015-03-26   NaN   NaN   NaN   NaN   NaN   NaN   NaN  1098.31   NaN   NaN   NaN   NaN 
2015-03-27   NaN 50893.42   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN 

注:(!這是最有可能的一個bug)asfreq刪除索引的名字

現在你可以ffill:

In [13]: df1['value'].unstack(0).asfreq('D').ffill() 
Out[13]: 
item_uid 0F01ddgkRa 0F02BZeTr6 0F02BcIzNo 0F02F4gAMs 0F02Vwd6Ou 0F04OlAs0R 0F05GInfPa 0F05PQARFJ 0F06LFhBCK 0F06ryso80 0F07gg7Oth 0S0099v8iI 
2015-03-16   NaN   NaN   NaN   NaN   NaN   NaN  664.68   NaN   NaN  13.73   NaN   NaN 
2015-03-17   NaN   NaN  1230   NaN   NaN   NaN  664.68   NaN   NaN  13.73   NaN   NaN 
2015-03-18   NaN   NaN  1230   NaN   NaN  321.44  664.68  1074.31  211.49  13.73   NaN   NaN 
2015-03-19   NaN   NaN  1230   NaN  5709.33  321.44  664.68  1074.31  211.49  13.73  2325.7   NaN 
2015-03-20   NaN 51505.22  1230   NaN  5709.33  321.44  664.68  1074.31  211.49  12.00  2325.7   NaN 
2015-03-21   NaN 51505.22  1230   NaN  5709.33  321.44  664.68  1074.31  211.49  12.00  2325.7   NaN 
2015-03-22   NaN 51505.22  1230   NaN  5709.33  321.44  664.68  1074.31  211.49  12.00  2325.7   NaN 
2015-03-23   NaN 51837.97  1130   NaN  5709.33  321.44  664.68  1074.31  211.49  12.00  2325.7   NaN 
2015-03-24   NaN 51578.63  1130   NaN  5709.33  321.44  664.68  1074.31  211.49  12.00  2325.7   NaN 
2015-03-25  1414.71 51578.63  1130  1855.96  5709.33  321.44  664.68  1074.31  211.49  12.00  2325.7 10652.79 
2015-03-26  1414.71 51578.63  1130  1855.96  5709.33  321.44  664.68  1098.31  211.49  12.00  2325.7 10652.79 
2015-03-27  1414.71 50893.42  1130  1855.96  5709.33  321.44  664.68  1098.31  211.49  12.00  2325.7 10652.79 

和堆棧回來(注意:您可以dropna = false如果您想包括起始NAN):

In [14]: s = df1['value'].unstack(0).asfreq('D').ffill().stack() 

注意:如果您的訂購索引是重要的,您可以切換/排序它:

In [15]: s.index = s.index.swaplevel(0, 1) 

In [16]: s = s.sort_index() 

In [17]: s.index.names = ['item_uid', 'created_at'] # as this is lost earlier 

In [18]: s 
Out[18]: 
item_uid 
0F01ddgkRa 2015-03-25  1414.71 
      2015-03-26  1414.71 
      2015-03-27  1414.71 
0F02BZeTr6 2015-03-20 51505.22 
      2015-03-21 51505.22 
      2015-03-22 51505.22 
      2015-03-23 51837.97 
      2015-03-24 51578.63 
      2015-03-25 51578.63 
      2015-03-26 51578.63 
      2015-03-27 50893.42 
... 
0S0099v8iI 2015-03-25 10652.79 
      2015-03-26 10652.79 
      2015-03-27 10652.79 
Length: 100, dtype: float64 

這是否比groupby/resample應用解決方案更有效率取決於數據。對於非常稀疏的數據(有很多啓動NaN,假設你想刪除這些),我懷疑它不會那麼快。如果數據密集(或者您想保留最初的NaN),我懷疑這個解決方案應該更快。

+0

謝謝安迪。很有幫助!解決方案非常有意義。至於'asfreq('D')'你是否開啓了一個GitHub問題?否則請告訴我,我可以幫忙。 – 2015-04-07 13:44:46

+0

請[做](https://github.com/pydata/pandas/issues):)我還沒有檢查主人是否仍然如此。但如果是這樣,希望應該是一個簡單的修復! – 2015-04-07 21:08:11

相關問題