将日期与列表进行比较时,用更有效的方法替换for循环



编辑:标题已更改,以反映map的效率不如for循环。

原标题:在比较日期时用地图替换for循环

我有一个连续日期列表date_list和一个数据帧df,其中包含,就现在而言,包含一个名为Event Date的列,其中包含事件发生的日期:

Index Event Date
0     02-01-20
1     03-01-20
2     03-01-20

我想知道在给定日期之前发生了多少事件,格式为:

Date     Events
01-01-20   0
02-01-20   1
03-01-20   3

我目前这样做的方法如下:

for date in date_list:
event_rows = df.apply(lambda x: True if x['Event Date'] > date else False , axis=1)
event_count = len(event_rows[event_rows == True].index)
temp = [date,event_count]  
pre_df_list.append(temp)

其中列表pre_df_list稍后被转换为数据帧。

这种方法很慢,看起来很不雅,但我正在努力寻找一种有效的方法。

我认为它应该是类似于的东西

map(lambda x,y: True if x > y else False, df['Event Date'],date_list)

但这会成对比较列表中的每个项目,这不是我想要的。

我很感激当我有工作代码时寻求帮助可能很奇怪,但我正在努力减少对循环的依赖,因为它们目前对我来说有点像拐杖。此外,我在完整的数据中有多个不同的事件需要跟踪,每个事件循环大约1000个日期的速度将非常慢。

使用groupby()size()获取每个日期的计数,使用cumsum()获取累积和,即包括特定行之前的所有日期。

from datetime import date, timedelta
import random
import pandas as pd 
# example data
dates = [date(2020, 1, 1) + timedelta(days=random.randrange(1, 100, 1)) for _ in range(1000)]
df = pd.DataFrame({'Event Date': dates})
# count events <= t
event_counts = df.groupby('Event Date').size().cumsum().reset_index()
event_counts.columns = ['Date', 'Events']
event_counts

Date  Events
0   2020-01-02      13
1   2020-01-03      23
2   2020-01-04      34
3   2020-01-05      42
4   2020-01-06      51
..         ...     ...
94  2020-04-05     972
95  2020-04-06     981
96  2020-04-07     989
97  2020-04-08     995
98  2020-04-09    1000

然后,如果date_list文件中的日期不存在于数据帧中,请将date_list转换为数据帧并合并以前的结果。fillna(method='ffill')将填充数据中间的间隙,而最后一个fillna(0)则表示列的开头有间隙。

date_list = [date(2020, 1, 1) + timedelta(days=x) for x in range(150)]
date_df = pd.DataFrame({'Date': date_list})
merged_df = pd.merge(date_df, event_counts, how='left', on='Date')
merged_df.columns = ['Date', 'Events']
merged_df = merged_df.fillna(method='ffill').fillna(0)

除非我误解了你的目标,否则在我看来,你可以简单地使用pandas DataFrames的能力来与单个值进行比较,并像这样对数据帧进行切片:

>>> df = pd.DataFrame({'event_date': [date(2020,9, 1), date(2020, 9, 2), date(2020, 9, 3)]})
>>> df
event_date
0  2020-09-01
1  2020-09-02
2  2020-09-03
>>> df[df.event_date > date(2020, 9, 1)]
event_date
1  2020-09-02
2  2020-09-03

最新更新