【问题标题】:assessing if date time function in each row of df falls within range of date time in another df评估 df 每一行中的日期时间函数是否在另一个 df 中的日期时间范围内
【发布时间】:2019-08-22 13:31:30
【问题描述】:

我是 python 新手,需要一些关于日期时间函数的问题的帮助。

我有df_a,其中有一个标题为time 的列,我正在尝试在此df_a 中创建一个新列id

我希望id 列由时间是否包含在“date”和“date_new”之间的df_b 列的时间范围内来确定,例如第一行的日期为“ 2019-01-07 20:52:41”和“2019-01-07 21:07:41”的“date_new”(15 分钟的时间间隔),我希望该行的索引显示为我的 id在df_a 中,当时间为“2019-01-07 20:56:30”时(即 id=0)等等df_a 中的所有行,

这个问题很相似,但我一直在想如何让它和我一起工作

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: 无法处理非唯一索引

需要注意的是,df_b 中的范围并不总是唯一的,这意味着一些间隔包含相同的时间段,在这些情况下,如果它使用它所在的 df_b 中第一个时间段的 id 就可以了,另外 df_b 中有 200 多行,df_a 有 2000 多行,因此以 for-loop 类型格式定义每个时间段需要很长时间,除非有比定义每个时间段更简单的方法,提前谢谢为您的所有帮助!如果这可以使用任何澄清,请告诉我!

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

【问题讨论】:

  • 请提供您的数据框示例和预期结果。
  • 请注意,df_a["time"] 中的最后一个值在预期结果中具有不同的值(2019-01-08 与 2019-01-07)。
  • 谢谢指正,应该是01-08

标签: python pandas datetime for-loop series


【解决方案1】:

pandas 对非 equi 连接没有很好的支持,这是您正在寻找的,但它确实有一个函数 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]

【讨论】:

    【解决方案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
    

    【讨论】:

    • 嘿,非常感谢您的帮助!这行得通,但确实需要很长时间才能运行
    猜你喜欢
    • 1970-01-01
    • 2017-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-26
    • 1970-01-01
    • 2020-10-09
    • 2019-12-27
    相关资源
    最近更新 更多