Python 有效地用“重新编制一级索引”;“正向填充”;在多索引数据帧中

Python 有效地用“重新编制一级索引”;“正向填充”;在多索引数据帧中,python,pandas,Python,Pandas,考虑以下数据帧: 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-

考虑以下数据帧:

                          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
我需要在这两个日期之间的每个日期对两个日期之间的完整数据帧进行采样,传播最后看到的值。取样应在每个
项目中独立/单独进行

例如,如果我们要在
2015-03-20
2015-03-29
之间为
0F02BZeTr6
取样,我们应该得到:

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
缺少的条目

解决类似问题,但仅针对一个组(即一个级别)。相反,此问题询问如何在每组(
item\u uid
)内分别执行相同的操作。虽然我可以拆分输入数据帧并遍历每个组(每个
item\u uid
),然后将结果缝合在一起,但我想知道是否还有更有效的方法

当我执行以下操作时(请参阅):

我得到:

TypeError: Fill method not supported if level passed

你有两个选择,最简单的方法是简单地取消第一个级别的堆叠,然后取消填充。我认为这比groupby/重采样解决方案更清楚地说明了正在发生的事情(我怀疑它也会更快,具体取决于数据):

如果缺少某些日期,则必须重新编制索引(假设有开始和结束日期,否则可以手动执行此操作,例如使用
pd.date\u range
):

注意:
asfreq
删除索引的名称(很可能是一个bug!)

现在你可以说:

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
并将其堆叠回去(注意:如果要包含起始NaN,可以dropna=False):

注意:如果您认为索引的顺序很重要,可以对其进行切换/排序:

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/重采样应用解决方案更有效取决于数据。对于非常稀疏的数据(有大量启动NaN,假设您想删除这些数据),我怀疑它不会那么快。如果数据密集(或者您希望保留初始NaN),我怀疑此解决方案应该更快。

谢谢Andy。非常有帮助!这个解决方案非常有意义。至于
asfreq('D')
您是否将GitHub问题作为bug打开?让我知道,否则,我可以帮你。请:)我还没有检查过师父是否仍然是这样。但如果是这样的话,希望这应该是一个简单的解决办法!
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
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
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