2

问题

  • 我希望 Pandas.resample()方法的结果具有 2 级索引。正如您可以在下面的示例中查看的那样,对 的重新采样good_example_df会产生 2 级索引。
  • index_list当我将from的第二个元素更改为datetime(2020,1,2,12,39,59)todatetime(2020,1,3,12,39,59)时, .resample() 方法只给了我 1 级索引。这个例子是用 给出的bad_example_df。这是我不想发生的事情。
  • 如何使.resample()方法的结果始终具有 2 级索引,就像 good_example_df 一样?
  • 我问这个问题的原因是我希望重采样方法的结果是一致的。我不希望方法的结果因输入而异。

代码示例

import pandas as pd
from datetime import datetime, time

index_list = [datetime(2020,1,2,2,43,59), datetime(2020,1,2,12,39,59),datetime(2020,1,3,21,42,59),
              datetime(2020,1,4,2,53,59), datetime(2020,1,4,19,17,59)]
data_dict = {'return': [1.003, 1.02, 1.06, 1.02, 1.03],
             'stock' : ['AMZN', 'APPL', 'NVDA', 'MSFT', 'AMZN']}

good_example_df = pd.DataFrame(data = data_dict, index = index_list)
good_example_df

>>                    return  stock
2020-01-02  2:43:59   1.003    AMZN
2020-01-02 12:39:59   1.020    APPL
2020-01-03 21:42:59   1.060    NVDA
2020-01-04 02:53:59   1.020    MSFT
2020-01-04 19:17:59   1.030    AMZN

good_example_df.resample("D").apply(lambda x: x[:2])

>>                               return  stock
2020-01-02  2020-01-02 02:43:59   1.003   AMZN
            2020-01-02 12:39:59   1.020   APPL
2020-01-03  2020-01-03 21:42:59   1.060   NVDA
2020-01-04  2020-01-04 02:53:59   1.020   MSFT
            2020-01-04 19:17:59   1.030   AMZN

new_index_list = [datetime(2020,1,2,2,43,59), datetime(2020,1,3,12,39,59),datetime(2020,1,3,21,42,59),
                  datetime(2020,1,4,2,53,59), datetime(2020,1,4,19,17,59)]

bad_example_df = pd.DataFrame(data = data_dict, index = new_index_list)
bad_example_df

>>                    return  stock
2020-01-02  2:43:59   1.003    AMZN
2020-01-03 12:39:59   1.020    APPL
2020-01-03 21:42:59   1.060    NVDA
2020-01-04 02:53:59   1.020    MSFT
2020-01-04 19:17:59   1.030    AMZN

bad_example_df.resample("D").apply(lambda x: x[:2])

>>>                return          stock
2020-01-02         1.003            AMZN
2020-01-03  [1.02, 1.06]    [APPL, NVDA]
2020-01-04  [1.02, 1.03]    [MSFT, AMZN]

4

1 回答 1

1

您的输出基本上只是相同的数据,但带有一个附加索引,时间四舍五入到天。 如果这就是您要实现的目标,请不要使用resample. 你不需要它,你可以重置索引:

In[]:
bad_example_df.set_index([bad_example_df.index.floor('D'), bad_example_df.index])

Out[]:
                                return stock
2020-01-02 2020-01-02 02:43:59   1.003  AMZN
2020-01-03 2020-01-03 12:39:59   1.020  APPL
           2020-01-03 21:42:59   1.060  NVDA
2020-01-04 2020-01-04 02:53:59   1.020  MSFT
           2020-01-04 19:17:59   1.030  AMZN

OTOH,您lambda看起来好像每天都在尝试获取前两个值。如果是这种情况,我认为apply这不是您想要使用的(大概是resample().apply()迭代方式的 b/c,请参见此处)。请注意,如果您将第一个日期更改为一月第一,您会得到更糟糕的意外输出:

In[]:
third_index_list = [datetime(2020,1,1,2,43,59), datetime(2020,1,2,12,39,59),datetime(2020,1,3,21,42,59),
              datetime(2020,1,4,2,53,59), datetime(2020,1,4,19,17,59)]

terrible_example_df = pd.DataFrame(data = data_dict, index = third_index_list)
terrible_example_df.resample("D").apply(lambda x: x[:2])

Out[]:
                  return         stock
2020-01-01         1.003          AMZN
2020-01-02          1.02          APPL
2020-01-03          1.06          NVDA
2020-01-04  [1.02, 1.03]  [MSFT, AMZN]
#now the dtype is object and lots of operations will fail!

因此,我认为您good_example_df恰好给出了预期的输出,而您bad_example_df恰好给出了意外但仍然有效的输出,但这两者都可能是对resample().apply(). TBH 我不明白apply每个示例中的不同之处。

相反,它看起来像使用groupbyand groupby().apply()(与 resample 不同apply!)可以为您提供一致的输出(据我所知):

In[]:
bad_example_df.groupby(pd.Grouper(freq='D')).apply(lambda x: x[:2])

Out[]: 
                                return stock
2020-01-02 2020-01-02 02:43:59   1.003  AMZN
2020-01-03 2020-01-03 12:39:59   1.020  APPL
           2020-01-03 21:42:59   1.060  NVDA
2020-01-04 2020-01-04 02:53:59   1.020  MSFT
           2020-01-04 19:17:59   1.030  AMZN
#works for terrible_example_df as well

还有TBH,这里我不明白为什么要创建两个索引,但它似乎工作!

于 2020-07-23T22:11:25.133 回答