Tax*_*xxi 9 python date dataframe pandas
让我们直接进入问题.以下是每日数据:
AAA BBB CCC
date
2012-04-16 44.48 28.48 17.65
2012-04-17 44.59 28.74 17.65
2012-04-18 44.92 28.74 17.72
2012-04-19 44.92 28.62 17.72
2012-04-20 45.09 28.68 17.71
2012-04-23 45.09 28.40 17.76
2012-04-24 45.09 28.51 17.73
2012-04-25 45.01 28.76 17.73
2012-04-26 45.40 28.94 17.76
2012-04-27 45.57 29.02 17.79
2012-04-30 45.45 28.90 17.80
2012-05-01 45.79 29.07 17.80
2012-05-02 45.71 28.98 17.77
2012-05-03 45.44 28.81 17.79
2012-05-04 45.05 28.48 17.79
2012-05-07 45.05 28.48 17.79
2012-05-08 45.00 28.40 17.93
2012-05-09 44.87 28.30 17.94
2012-05-10 44.93 28.34 17.85
2012-05-11 44.86 28.30 17.96
... ... ...
Run Code Online (Sandbox Code Playgroud)
我想选择从第一行开始的每月递增的行,即索引为2012-04-16,2012-05-16,2012-06-16,...的行.我可以使用relativedelta并手动添加它们,但我想知道是否有更有效的方法.我尝试重新取样,但我只能选择每月的第一个或最后一个df.resample('M').first().
使问题更复杂的原因是缺少某些日期; 他们是工作日,但不是美国的工作日.有几种方法可以解决此问题:
选择最接近日期的确切日期或更早的日期.如果此日期不存在,则开始查找以后的日期.
选择最接近日期的确切日期或更晚的日期.如果此日期不存在,则开始查找较早的日期.
无论是早期还是晚期,选择最接近确切日期的日期; 我可以用min(df.index, key=lambda x: abs(x - (df.index[0] + relativedelta(months=1))).
在每种情况下,我都想知道哪种方法最有效且易于阅读.在最后一个代码示例中,月份是一个变量,因此我不确定是否可以将其作为lambda过程并使用"apply".
提前致谢.
jpp*_*jpp 11
在我们查看您的数据之前,让我们先看看如何DatetimeIndex在每个月的特定日期创建一个数据.由于pd.date_range每月定期频率占用每个月的最后一天,我们可以简单地添加固定天数:
idx = pd.date_range('2018-04-01', '2018-07-01', freq='1M') + pd.DateOffset(days=16)
DatetimeIndex(['2018-05-16', '2018-06-16', '2018-07-16'],
dtype='datetime64[ns]', freq=None)
Run Code Online (Sandbox Code Playgroud)
现在让我们来看一个丢失了大约第 16 天的示例数据帧:
AAA BBB CCC
date
2012-04-16 44.48 28.48 17.65
2012-04-17 44.59 28.74 17.65
2012-05-15 45.79 29.07 17.80
2012-05-16 45.71 28.98 17.77
2012-05-17 45.44 28.81 17.79
2012-06-15 44.87 28.30 17.94
2012-06-17 44.95 28.50 17.98
2012-07-14 44.65 28.25 17.87
2012-07-17 44.55 28.75 17.75
Run Code Online (Sandbox Code Playgroud)
正如您所提到的,您可以通过多种方式决定如何选择不匹配的日子,无论是向后,向前,还是寻找最近的,没有偏好.您需要考虑在项目环境中最合适的内容.以下是一个坚持Pandas功能并避免自定义lambda功能的解决方案.
DatetimeIndex首先创建一个只指定了必需索引的数据框:
offset = pd.DateOffset(days=16)
start_date = df.index[0]-pd.DateOffset(months=1)
idx = pd.date_range(start_date, df.index[-1], freq='1M') + offset
df_idx = pd.DataFrame(index=idx)
Run Code Online (Sandbox Code Playgroud)
请注意,我们需要从start参数中减去一个月,以便在添加16天后不会省略第一个月.现在您可以使用pd.merge_asof多种选项: -
merge_asof将direction参数指定为'backward'(默认),'forward'或'nearest'根据需要指定.例如,使用'forward':
print(pd.merge_asof(df_idx, df, left_index=True, right_index=True, direction='forward'))
AAA BBB CCC
2012-04-16 44.48 28.48 17.65
2012-05-16 45.71 28.98 17.77
2012-06-16 44.95 28.50 17.98
2012-07-16 44.55 28.75 17.75
Run Code Online (Sandbox Code Playgroud)
现在这可能足以满足您的需求.
编辑:如果要保留数据框中的索引,可以反转合并的方向并使用'backward'而不是'forward':
res = pd.merge_asof(df.reset_index(),
df_idx.reset_index().rename(columns={'index': 'date_idx'}),
left_on='date', right_on='date_idx', direction='backward')
res['diff'] = (res['date'] - res['date_idx']).dt.days.abs()
grouper = res['date'].dt.strftime('%Y-%m')
res = res[res['diff'] == res.groupby(grouper)['diff'].transform('min')]
print(res)
date AAA BBB CCC date_idx diff
0 2012-04-16 44.48 28.48 17.65 2012-04-16 0
3 2012-05-16 45.71 28.98 17.77 2012-05-16 0
6 2012-06-17 44.95 28.50 17.98 2012-06-16 1
8 2012-07-17 44.55 28.75 17.75 2012-07-16 1
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
419 次 |
| 最近记录: |