评估df每行中的日期时间函数是否落在另一df中的日期时间范围内

时间:2019-04-01 11:35:26

标签: python pandas for-loop

我是python的新手,需要一些有关日期时间函数的问题的帮助。我有df_a,该列的标题为“ time”,并且我正在尝试在此df_a中创建新的列“ id”。我希望通过“时间”是否在“ date”和“ date_new”之间的df_b列中的时间范围内确定“ id”列,例如,第一行的日期为“ 2019-01-07” 20:52:41”和“ 2019-01-07 21:07:41”的“ date_new”(15分钟的时间间隔),我希望此行的索引在df_a中显示为我的ID,对于df_a中的所有行,时间均为“ 2019-01-07 20:56:30”(即,id = 0),依此类推,

这个问题很相似,但是随着我不断得到

,我无法弄清楚如何使其与我的作品兼容

python assign value to pandas df if falls between range of dates in another df

s = pd.Series(df_b['id'].values,pd.IntervalIndex.from_arrays(df_b['date'],df_b['date_new'])) 
df_a['id']=df_a['time'].map(s)

ValueError: cannot handle non-unique indices

一个警告是,df_b中的范围并不总是唯一的,这意味着某些间隔包含相同的时间段,在这些情况下,如果它使用df_b中第一个时间段的ID,此外,df_b中有200多行,而df_a中有2000行,因此以for循环类型格式定义每个时间段将花费很长时间,除非有比定义每个时间段更简单的方法,请提前感谢您为您的所有帮助!如果可以进行任何说明,请告诉我!

df_a

time                    id
2019-01-07 22:02:56     NaN
2019-01-07 21:57:12     NaN
2019-01-08 09:35:30     NaN


df_b

date                    date_new               id
2019-01-07 21:50:56    2019-01-07 22:05:56     0
2019-01-08 09:30:30    2019-01-08 09:45:30     1

Expected Result

df_a     
time                    id
2019-01-07 22:02:56     0
2019-01-07 21:57:12     0
2019-01-08 09:35:30     1

2 个答案:

答案 0 :(得分:2)

让我重新说明您的问题。对于数据帧df_a中的每一行,您要检查其在df_a['time']中的值是否在df_b['date']df_b['date_new']列中的值给定的间隔内。如果是这样,请将df_a["id"]中的值设置为对应的df_b["id"]中的值。

如果这是您的问题,这是一个(非常粗糙的)解决方案:

for ia, ra in df_a.iterrows():
    for ib, rb in df_b.iterrows():
        if (ra["time"]>=rb['date']) & (ra["time"]<=rb['date_new']):
            df_a.loc[ia, "id"] = rb["id"]
            break

答案 1 :(得分:1)

pandas对非等额联接没有很好的支持,这正是您要寻找的,但是它确实有一个功能merge_asof,您可能需要检查一下: http://pandas.pydata.org/pandas-docs/version/0.22/generated/pandas.merge_asof.html

这应该大大加快您的加入速度。

例如:

df_a = pd.DataFrame({'time': ['2019-01-07 22:02:56', '2019-01-07 21:57:12', '2019-01-08 09:35:30']})
df_b = pd.DataFrame({'date': ['2019-01-07 21:50:56', '2019-01-08 09:30:30'], 'date_new': ['2019-01-07 22:05:56', '2019-01-08 09:45:30'], 'id':[0,1]})
df_a['time'] = pd.to_datetime(df_a['time'])
df_b['date'] = pd.to_datetime(df_b['date'])
df_b['date_new'] = pd.to_datetime(df_b['date_new'])

#you need to sort df_a first before using merge_asof
df_a.sort_values('time',inplace=True)
result = pd.merge_asof(df_a, df_b, left_on='time', right_on='date')

#get rid of rows where df_a.time values are greater than df_b's new date
result = result[result.date_new > result.time]