Python DataFrame从每日数据中选择按月递增的行[英] Python DataFrame selecting the rows with monthly increment from daily data

本文是小编为大家收集整理的关于Python DataFrame从每日数据中选择按月递增的行的处理方法,想解了Python DataFrame从每日数据中选择按月递增的行的问题怎么解决?Python DataFrame从每日数据中选择按月递增的行问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

让我们直接进入问题.以下是每日数据:

             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
           ...    ...    ...

我想从第一行开始选择每月增量,即索引为 2012-04-16,2012-12-16,2012的行-06-16,... .我可以只使用Relativedelta并手动添加它们,但我想知道是否有更有效的方法.我尝试重新采样,但我只能选择每个月的第一个或最后一个或最后一个,如df.resample('M').first().

使问题更加复杂的是缺少一些日期.它们是工作日,但不是美国的工作日.有几种解决此问题的方法:

  1. 选择确切的日期或最接近日期的日期.如果 这样的日期不存在,然后开始寻找以后的日期.

  2. 选择确切的日期或最接近日期的日期.如果是这样 日期不存在,然后开始查找较早的日期.

  3. 选择最接近确切日期的日期 或迟到;我可以使用min(df.index, key=lambda x: abs(x - (df.index[0] + relativedelta(months=1))).

,在每种情况下,我都想知道哪种方法是最有效且易于阅读的方法.在上一个代码示例中,这个月是一个变量,因此我不确定是否可以将其作为lambda过程并使用"应用".

预先感谢.

推荐答案

在查看您的数据之前,让我们首先看看如何在每个月的特定一天中创建DatetimeIndex.由于常规 pd.date_range 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)

现在,让我们以一个示例数据框架,其中有大约16 th 丢失:

              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

您提到的是,有多种方法可以决定如何选择非匹配的日子,以向后,向前或寻找最近而无需偏好. 您需要考虑在项目上下文中最合适的内容.是一种解决熊猫功能并避免自定义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)

请注意,我们需要从开始参数中减去一个月,以便在添加16天后不会省略第一个月.现在,您可以使用 pd.merge_asof 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

现在这可能足以满足您的需求.


编辑:如果要将索引从数据框架中保留,则可以逆转合并的方向并使用'backward'而不是'backward':

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

本文地址:https://www.itbaoku.cn/post/1727877.html