Pandas使用条件参数查找最近的日期时间索引



我试图找到我的表最近的日期时间索引。我用这篇文章作为起点,我用这个MWE:

import os
import numpy as np
import pandas as pd
from datetime import datetime, date, timedelta
df = pd.DataFrame() 
df['datetime'] = pd.date_range(start='2019-01-01', end='2021-01-01', freq='H')
df = df.set_index('datetime')
df['year'] = pd.DatetimeIndex(df.index).year
df['mnth'] = pd.DatetimeIndex(df.index).month
df['day'] = pd.DatetimeIndex(df.index).day
df['dow'] = pd.DatetimeIndex(df.index).dayofweek # Mon=0, ..., Sun=6
df['hour'] = pd.DatetimeIndex(df.index).hour
years = df.year.unique()
idxlist = []
for y in years:
idx1 = df.loc[((df.year==y) & (df.mnth==4) & (df.day<=7) & (df.dow==6) & (df.hour==2))]
#idx1 = df.iloc[df.get_loc(((df.year==y) & (df.mnth==4) & (df.day<=7) & (df.dow==6) & (df.hour==2)), method='nearest')]
idxlist.append(idx1)

编辑基于Michael Delgado的评论:

我有几年的每日数据,包括正确的日子(每年四月的第一个星期日)。

尽管这适用于我的MWE,但我的实际数据集包含丢失的数据,并且可能没有精确到凌晨2点的数据。数据的间隔大约为20-35min,因此最接近的值应该距离2AM目标小于15min。

我想找到四月第一个星期天凌晨2点最近的日期时间。这是每年在数据框架,但我不确定如何做到这一点。

根据您的评论,似乎您可以依赖每年在您想要的时间(4月1日星期日)的一个小时内始终拥有数据。在这种情况下,您可以采用更简单的方法。

使用时间变化的示例数据集:

In [4]: df = pd.DataFrame(
...:     ...:     {'val': np.arange(24*366*10)},
...:     ...:     index=(
...:     ...:         pd.date_range('2010-01-01', periods=24*366*10, freq='H')
...:     ...:         + pd.to_timedelta(np.random.randint(-30, 30, size=(24*366*10)), unit='minutes')
...:     ...:     ),
...:     ...: )
In [5]: df
Out[5]:
val
2010-01-01 00:14:00      0
2010-01-01 01:20:00      1
2010-01-01 01:46:00      2
2010-01-01 03:20:00      3
2010-01-01 03:51:00      4
...                    ...
2020-01-08 18:48:00  87835
2020-01-08 19:46:00  87836
2020-01-08 21:07:00  87837
2020-01-08 22:06:00  87838
2020-01-08 23:11:00  87839
[87840 rows x 1 columns]

我们可以根据四舍五入到最接近的2小时的时间进行过滤:

within_an_hour = df[
(df.index.month==4)
& (df.index.day<=7)
& (df.index.day_of_week == 6)
& (df.index.round('2H').hour == 2)
]

然后,我们可以通过取每年2小时四舍五入值的最小绝对差值来选择最接近的指数:

In [15]: closest_indices = (
...:     within_an_hour
...:     .groupby(within_an_hour.index.year)
...:     .apply(
...:         lambda x: x.index.values[np.argmin(abs(x.index - x.index.round('2H')))]
...:     )
...: )
In [16]: closest_indices
Out[16]:
2010   2010-04-04 02:17:00
2011   2011-04-03 02:22:00
2012   2012-04-01 01:49:00
2013   2013-04-07 01:39:00
2014   2014-04-06 02:01:00
2015   2015-04-05 01:58:00
2016   2016-04-03 02:12:00
2017   2017-04-02 01:54:00
2018   2018-04-01 02:22:00
2019   2019-04-07 02:13:00
dtype: datetime64[ns]

这有点难度,因为"每年四月的第一个星期日"需要几个步骤来计算。您可以通过几种方法来实现这一点,但我将首先计算目标日期所在年份中最接近的目标日期,以及下一年(因为4月总是在一年的第一部分,所以该日期永远不会接近前一年的4月),然后找到与这两个目标之间的最小绝对差值。

第一步,我将用一些随机偏移(+/- 30分钟)和更长的时间序列来扩展您的MWE。我还添加了一个值列,以便df显示为框架:

In [26]: df = pd.DataFrame(
...:     {'val': np.arange(24*366*10)},
...:     index=(
...:         pd.date_range('2010-01-01', periods=24*366*10, freq='H')
...:         + pd.to_timedelta(np.random.randint(-30, 30, size=(24*366*10)), unit='minutes')
...:     ),
...: )
In [27]: df
Out[27]:
val
2010-01-01 00:29:00      0
2010-01-01 01:09:00      1
2010-01-01 01:43:00      2
2010-01-01 03:14:00      3
2010-01-01 03:54:00      4
...                    ...
2020-01-08 18:31:00  87835
2020-01-08 20:21:00  87836
2020-01-08 20:54:00  87837
2020-01-08 21:47:00  87838
2020-01-08 23:11:00  87839

接下来,我查找每行年份的4月第一个星期日的日期(凌晨2点):

In [28]: apr1 = pd.to_datetime({'year': df.index.year, 'month': 4, 'day': 1, 'hour': 2})
In [29]: apr_first_sun = apr1 + pd.to_timedelta(6 - apr1.dt.weekday, unit='day')
In [30]: apr_first_sun
Out[30]:
0       2010-04-04 02:00:00
1       2010-04-04 02:00:00
2       2010-04-04 02:00:00
3       2010-04-04 02:00:00
4       2010-04-04 02:00:00
...
87835   2020-04-05 02:00:00
87836   2020-04-05 02:00:00
87837   2020-04-05 02:00:00
87838   2020-04-05 02:00:00
87839   2020-04-05 02:00:00
Length: 87840, dtype: datetime64[ns]
In [31]: apr1 = pd.to_datetime({'year': df.index.year + 1, 'month': 4, 'day': 1, 'hour': 2})
In [32]: next_apr_first_sun = apr1 + pd.to_timedelta(6 - apr1.dt.weekday, unit='day')

接下来,找出更接近的绝对差值:

In [36]: nearer_abs_diff = np.minimum(abs(df.index - apr_first_sun.values), abs(df.index - next_apr_first_sun.values))
In [37]: nearer_abs_diff
Out[37]:
TimedeltaIndex(['93 days 01:31:00', '93 days 00:51:00', '93 days 00:17:00',
'92 days 22:46:00', '92 days 22:06:00', '92 days 20:54:00',
'92 days 20:23:00', '92 days 19:25:00', '92 days 18:12:00',
'92 days 16:48:00',
...
'87 days 12:19:00', '87 days 11:12:00', '87 days 09:36:00',
'87 days 08:31:00', '87 days 07:36:00', '87 days 07:29:00',
'87 days 05:39:00', '87 days 05:06:00', '87 days 04:13:00',
'87 days 02:49:00'],
dtype='timedelta64[ns]', length=87840, freq=None

最后,找到最小绝对差的位置索引,并使用它来索引数据帧:

In [38]: idx = np.argmin(nearer_abs_diff)
In [39]: df.iloc[idx]
Out[39]:
val    37346
Name: 2014-04-06 02:14:00, dtype: int64

相关内容

  • 没有找到相关文章