我有一个 Pandas 数据框,我想在其中重新采样到每个月的第三个星期五。
np.random.seed(0)
#requested output:
dates = pd.date_range("2018-01-01", "2018-08-31")
dates_df = pd.DataFrame(data=np.random.random(len(dates)), index=dates)
mask = (dates.weekday == 4) & (14 < dates.day) & (dates.day < 22)
dates_df.loc[mask]
但是当缺少第三个星期五时(例如,删除二月三 星期五),我想要最新的值(value)(截至 2018-02-15)。使用掩码给我下一个值(2 月 17 日而不是 2 月 15 日):
# remove February third Friday:
dates_df = dates_df.drop([pd.to_datetime("2018-02-16")])
mask = (dates.weekday == 4) & (14 < dates.day) & (dates.day < 22)
dates_df.loc[mask]
结合使用每月重采样和 loffset 可以得到带有索引偏移的月末值,这也不是我想要的:
from pandas.tseries.offsets import WeekOfMonth
dates_df.resample("M", loffset=WeekOfMonth(week=2, weekday=4)).last()
是否有替代方案(最好使用重新采样)而不必先重新采样到每日值然后添加掩码(这需要很长时间才能在我的数据帧上完成)
最佳答案
你的第二次尝试是在正确的方向 IIUC,你只需要使用 WeekOfMonth 作为规则重新采样,而不是将其用作偏移量:
dates_df.resample(WeekOfMonth(week=2, weekday=4)).asfreq().dropna()
这种方法不会抵消索引,它应该只返回每个月的第三个星期五的数据。
Dealing with Missing 3rd Friday:
使用上面的代码,如果您缺少第 3 个星期五,则整个月都将被排除在外。但是根据你想如何处理丢失的数据,你可以bfill
, ffill
, pad
..你可以修改上面的内容如下:
dates_df.resample(rule=WeekOfMonth(week=2,weekday=4)).bfill().asfreq(freq='D').dropna()
上面的代码将用下一个值bfill
缺失的第 3 个星期五。
Update: Lets work with a fixed data set instead of
np.random
:
# create a smaller daterange
dates = pd.date_range("2018-05-01", "2018-08-31")
# create a data with only 1,2,3 values
data = [1,2,3] * int(len(dates)/3)
dates_df = pd.DataFrame(data=data, index=dates)
dates_df.head()
# Output:
2018-05-01 1
2018-05-02 2
2018-05-03 3
2018-05-04 1
2018-05-05 2
现在让我们通过手动选择来检查每个月的第三个星期五的数据:
dates_df.loc[[
pd.Timestamp('2018-05-18'),
pd.Timestamp('2018-06-15'),
pd.Timestamp('2018-07-20'),
pd.Timestamp('2018-08-17')
]]
Output:
2018-05-18 3
2018-06-15 1
2018-07-20 3
2018-08-17 1
如果您没有遗漏第 3 个星期五并运行之前提供的代码:
dates_df.resample(rule=WeekOfMonth(week=2,weekday=4)).asfreq().dropna()
将产生以下输出:
2018-05-18 3
2018-06-15 1
2018-07-20 3
2018-08-17 1
如您所见,索引并未在此处移动,它返回每个月第三个星期五的准确值。
现在假设您确实缺少一些第 3 个星期五,具体取决于您希望如何处理(使用前一个值:ffill
,或下一个值 bfill
):
- pad / ffill: propagate last valid observation forward to next valid
- backfill / bfill: use NEXT valid observation to fill gap
dates_df.drop(index=pd.Timestamp('2018-08-17')).resample(rule=WeekOfMonth(week=2, weekday=4)).ffill().asfreq(freq='D').dropna()
2018-05-18 3
2018-06-15 1
2018-07-20 3
2018-08-17 3
dates_df.drop(index=pd.Timestamp('2018-08-17')).resample(rule=WeekOfMonth(week=2, weekday=4)).bfill().asfreq(freq='D').dropna()
2018-04-20 1
2018-05-18 3
2018-06-15 1
2018-07-20 3
2018-08-17 2
如果说整个索引像您的示例一样移动:
dates_df.resample(rule='M', loffset=WeekOfMonth(week=2, weekday=4)).asfreq().dropna()
# Output:
2018-06-15 1
2018-07-20 1
2018-08-17 2
2018-09-21 3
那里发生的事情是您按规则“M”(月末)重新采样,然后在每个月的第三个星期五之前抵消(向前移动)索引。
正如您在偏移之前看到的,它看起来像这样:
dates_df.resample(rule='M').asfreq().dropna()
# Output
2018-05-31 1
2018-06-30 1
2018-07-31 2
2018-08-31 3
关于python - Pandas 在一个月内重新采样到特定的工作日,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52495310/