pandas .resample() 不适用于某些示例。为什么?
pandas .resample() does not work with some examples. Why?
问题
- 我希望 Pandas
.resample()
方法的结果有 2 级索引。正如您可以在下面的示例中查看的那样,good_example_df
的重采样会产生 2 级索引。
- 当我将
index_list
的第二个元素从 datetime(2020,1,2,12,39,59)
更改为 datetime(2020,1,3,12,39,59)
时,.resample() 方法只给我一级索引。该示例以 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]
您的输出基本上只是相同的数据,但有一个额外的索引,时间向下舍入到天。 如果这是您要实现的目标,请不要使用 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,see here)。请注意,如果您首先将第一个日期更改为一月,您会得到更糟糕的意外,输出:
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
在每个示例中的不同之处。
而不是,看起来使用groupby
和groupby().apply()
(不同于重采样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,这里我不明白为什么要创建两个索引,但它似乎有效!
问题
- 我希望 Pandas
.resample()
方法的结果有 2 级索引。正如您可以在下面的示例中查看的那样,good_example_df
的重采样会产生 2 级索引。 - 当我将
index_list
的第二个元素从datetime(2020,1,2,12,39,59)
更改为datetime(2020,1,3,12,39,59)
时,.resample() 方法只给我一级索引。该示例以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]
您的输出基本上只是相同的数据,但有一个额外的索引,时间向下舍入到天。 如果这是您要实现的目标,请不要使用 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,see here)。请注意,如果您首先将第一个日期更改为一月,您会得到更糟糕的意外,输出:
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
在每个示例中的不同之处。
而不是,看起来使用groupby
和groupby().apply()
(不同于重采样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,这里我不明白为什么要创建两个索引,但它似乎有效!