pandas - Pandas merge_asof() 给出重复匹配
问题描述
我有两个要合并的日期时间数据框。因为数据帧上的某些时间戳可能不完全相同,所以我认为最好使用 pandasmerge_asof()
函数。
我想在“最近”值上加入时间戳,但在给定的容差范围内(例如 +/- 5 分钟)。但是,该merge_asof()
函数似乎将时间戳与容差内的第一个数据帧的所有时间戳相匹配。下面的例子可以更好地解释这一点。
import pandas as pd
df1 = pd.date_range("2019-01-01 00:00:00", "2019-01-01 00:04:00", freq='20s')
df1 = pd.DataFrame(df1, columns=['time'])
df2 = pd.DataFrame(["2019-01-01 00:02:00"], columns=['time'])
df2['time'] = pd.to_datetime(df2['time'])
df2['df2_col'] = 'df2'
merged_df = pd.merge_asof(df1, df2, left_on='time', right_on='time',
tolerance=pd.Timedelta('40s'),
allow_exact_matches=True,
direction='nearest')
print (merged_df)
实际输出:
time df2_col
0 2019-01-01 00:00:00 NaN
1 2019-01-01 00:00:20 NaN
2 2019-01-01 00:00:40 NaN
3 2019-01-01 00:01:00 NaN
4 2019-01-01 00:01:20 df2
5 2019-01-01 00:01:40 df2
6 2019-01-01 00:02:00 df2
7 2019-01-01 00:02:20 df2
8 2019-01-01 00:02:40 df2
9 2019-01-01 00:03:00 NaN
10 2019-01-01 00:03:20 NaN
11 2019-01-01 00:03:40 NaN
12 2019-01-01 00:04:00 NaN
预期输出:
time df2_col
0 2019-01-01 00:00:00 NaN
1 2019-01-01 00:00:20 NaN
2 2019-01-01 00:00:40 NaN
3 2019-01-01 00:01:00 NaN
4 2019-01-01 00:01:20 NaN
5 2019-01-01 00:01:40 NaN
6 2019-01-01 00:02:00 df2
7 2019-01-01 00:02:20 NaN
8 2019-01-01 00:02:40 NaN
9 2019-01-01 00:03:00 NaN
10 2019-01-01 00:03:20 NaN
11 2019-01-01 00:03:40 NaN
12 2019-01-01 00:04:00 NaN
这是预期的行为吗?我怎样才能获得预期的结果?
解决方案
实际输出是预期的行为:merge_asof(left, right)
查找最近行中的每一行(在容差范围内)。你想要的略有不同:你想找到最接近的一行。恐怕熊猫没有内置功能。 left
right
left
right
为了实现你想要的,你可以做一个反转merge_asof(right, left)
,然后将结果与left
. 为了在反向merge_asof
结果中识别您需要的行,我们首先重置索引并将此信息用于第二次合并:
x = pd.merge_asof(df2, df1.reset_index(), left_on='time', right_on='time',
tolerance=pd.Timedelta('40s'),
allow_exact_matches=True,
direction='nearest')
merged_df = df1.merge(x[['df2_col','index']], how='left', left_index=True, right_on='index').set_index('index')
结果:
time df2_col
index
0 2019-01-01 00:00:00 NaN
1 2019-01-01 00:00:20 NaN
2 2019-01-01 00:00:40 NaN
3 2019-01-01 00:01:00 NaN
4 2019-01-01 00:01:20 NaN
5 2019-01-01 00:01:40 NaN
6 2019-01-01 00:02:00 df2
7 2019-01-01 00:02:20 NaN
8 2019-01-01 00:02:40 NaN
9 2019-01-01 00:03:00 NaN
10 2019-01-01 00:03:20 NaN
11 2019-01-01 00:03:40 NaN
12 2019-01-01 00:04:00 NaN
警告:在我们的示例中,df1 有一个未命名的索引。重置此索引会将其变为默认名称为“index”的列,我们在第二次合并中使用该列。但是,如果 df1 已经有一个名为“index”的列,那么新列的名称将是“index_0”,我们将不得不在第二次合并中使用这个名称而不是“index”。
推荐阅读
- java - 如何通过端口获取tomcat进程ID并结束该进程
- php - 无法显示 ajax 结果 WordPress
- c++ - Bazel 使用 soname 创建 C++ 共享库
- javascript - AngularJS ng-repeat 在地图(对象)上不实时更新 DOM
- azure - CosmosDB 表 API - 此 API 不支持 CORS 规则
- jquery - 查找包含相同文本的每组 div 的第一个实例
- gradle - 使用 Gradle 在 Dagger 2 中插入组件模块
- javascript - 请求函数中的 NodeJS 全局变量
- spring - Spring Session 不使用自定义 RedisTemplate bean
- php - 如何让我的会话数据正确存储?