python - 使用最近时间连接数据框并为特定对象填充缺失的时间戳
问题描述
我有两个数据框。
数据帧 #1 (df1):
1 object_name time_epoch_ms source data
2 a 1538518822490 source_1 some_data
3 b 1538528822490 source_2 some_data
4 b 1538538822490 source_2 some_data
5 b 1538548822490 source_3 some_data
6 b 1538558822490 source_1 some_data
7 c 1538568822490 source_2 some_data
8 c 1538578822490 source_2 some_data
9 c 1538588822490 source_2 some_data
... etc etc
数据帧#2(df2):
1 object_name time_epoch_ms new_data
2 a 1538518722490 x
3 b 1538528822490 y
4 b 1538518922490 z
5 b 1538519922490 a
6 b 1538598822490 b
7 c 1538548822490 c
8 c 1538538822490 c
9 c 1538528822490 d
... etc etc
这两个表中的条目提供了有关不同时间点具有 object_names 的对象的信息。
我想组合这两个表,以便数据帧#2 增加了 object_name 在数据帧#1 中指定的特定时间使用的源。
问题:两个表中的时间戳不完全匹配。表 2 中存在的一些时间戳在表 1 中不存在。但是,它们应该大致对应于小时。表 1 中的一些时间戳缺失,因此“最后可用数据”是最好的。
有没有办法使用熊猫的合并能力执行以下步骤?
- 匹配数据帧中的数据,以便 df2 根据 object_name 和 time_stamp 从 df1 获取“源”数据,以便 time_stamp 与最近的时间匹配。
- 如果特定小时的数据在 df2 中,但不在 df1 中,则从最后一个可用数据小时重试源,因此根据该对象存在的任何数据“填充”它。
- 如果 df2 中的对象不在 df1 中,则它得到一个“null”
我的做法:
我目前使用 .apply 从 df2 获取每一行,并在 df1 中找到该对象的所有时间戳(如果存在)。然后,我返回最接近的匹配项或 null。
我想知道是否有更优雅的方法可以使用 pandas 的合并或 concat 功能来做到这一点,但我无法理解在这种情况下如何使用它们以及如何处理填充数据并根据小时进行匹配(不做单独的预处理以获得一个小时列)。
解决方案
一般来说,Pandas 使“等连接”变得容易,但其他类型的连接有点困难。在这种情况下你很幸运,因为有一个很好的方法可以满足merge_asof
你的需要。
关于如何设置数据有点迂腐,但 MWE 是:
from io import StringIO
import pandas as pd
df1 = pd.read_table(StringIO("""1 object_name time_epoch_ms source data
2 a 1538518822490 source_1 some_data_1
3 b 1538528822490 source_2 some_data_2
4 b 1538538822490 source_2 some_data_3
5 b 1538548822490 source_3 some_data_4
6 b 1538558822490 source_1 some_data_5
7 c 1538568822490 source_2 some_data_6
8 c 1538578822490 source_2 some_data_7
9 c 1538588822490 source_2 some_data_8
"""), sep=r"\s+", index_col=0)
df2 = pd.read_table(StringIO("""1 object_name time_epoch_ms new_data
2 a 1538518722490 x
3 b 1538528822490 y
4 b 1538518922490 z
5 b 1538519922490 a
6 b 1538598822490 b
7 c 1538548822490 c
8 c 1538538822490 c
9 c 1538528822490 d
"""), sep=r"\s+", index_col=0)
pd.merge_asof(
df2.sort_values(['time_epoch_ms', 'object_name']),
df1.sort_values(['time_epoch_ms', 'object_name']),
by="object_name", on="time_epoch_ms",
direction='forward',
).sort_values(['object_name', 'time_epoch_ms'])
回馈:
object_name time_epoch_ms new_data source data
0 a 1538518722490 x source_1 some_data_1
1 b 1538518922490 z source_2 some_data_2
2 b 1538519922490 a source_2 some_data_2
3 b 1538528822490 y source_2 some_data_2
7 b 1538598822490 b NaN NaN
4 c 1538528822490 d source_2 some_data_6
5 c 1538538822490 c source_2 some_data_6
6 c 1538548822490 c source_2 some_data_6
另一个例子见Pandas 等效的 SQL non-equi JOIN。还有merge_ordered
,但我认为这对你的情况没有帮助。
推荐阅读
- python - Avoid foreground becomes into background on background substractor using OpenCV
- python - 在 pandas 中拆分列并保留第一个拆分
- python - 尝试将元组添加到列表中并添加字符 ' 破坏代码
- sql - Spark SQL CTE在查询中忽略命名空间
- flutter - 在颤动中返回并显示列表中的项目数
- google-cloud-platform - 对 Google API 的请求停止工作,我该如何调试该问题?
- c++ - KTX 图像文件可以是立方体贴图数组吗?
- python - 用于查找文档之间文本相似性的 keras LSTM 层的维数错误
- asp.net - MiniProfiler MVC SQL 计时不显示
- css - *ngFor 不同类的元素