2015-03-30 54 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

相关问题