在DataFrame中查找最近时间:两种时间格式数据集匹配需求
嘿,这个问题我熟,咱们一步步来搞定它!核心思路就是先把两个数据集的时间统一成pandas能识别的datetime格式,再计算每个时间点的最近匹配项。
具体实现步骤
1. 统一时间格式
首先得把两种不同的时间格式转换成标准的datetime类型:
- df1里的
A列是Unix秒级时间戳,用pd.to_datetime()时指定unit='s'就能解析; - df2里的
B列是ISO 8601格式的字符串,直接用pd.to_datetime()就能自动识别。
import pandas as pd # 你的原始数据 df1 = pd.DataFrame( {'A': [1499503900, 1512522054, 1412525061, 1502527681, 1512532303]}) df2 = pd.DataFrame( {'B' : ['2017-12-15T11:47:58.119Z', '2017-05-31T08:27:41.943Z', '2017-06-05T14:44:56.425Z', '2017-05-30T16:24:03.175Z' , '2017-07-03T10:20:46.333Z', '2017-06-16T10:13:31.535Z' , '2017-12-15T12:26:01.347Z', '2017-06-15T16:00:41.017Z', '2017-11-28T15:25:39.016Z', '2017-08-10T08:48:01.347Z'] }) # 转换时间格式 df1['A_datetime'] = pd.to_datetime(df1['A'], unit='s') df2['B_datetime'] = pd.to_datetime(df2['B'])
2. 匹配最近的时间
接下来为df1的每一行,在df2中找到时间差最小的记录。这里有两种方法,适合不同规模的数据集:
方法一:适合小规模数据集(简单直观)
用apply()遍历df1的每一行,计算当前时间与df2所有时间的绝对差,然后取差值最小的那一项:
def get_closest_time(row): # 计算当前时间和df2所有时间的绝对差值 time_diffs = abs(df2['B_datetime'] - row['A_datetime']) # 找到差值最小的索引 closest_idx = time_diffs.idxmin() # 返回对应的原始时间字符串和转换后的datetime return pd.Series( [df2.loc[closest_idx, 'B'], df2.loc[closest_idx, 'B_datetime']], index=['closest_B', 'closest_B_datetime'] ) # 把匹配结果合并到df1中 df1 = pd.concat([df1, df1.apply(get_closest_time, axis=1)], axis=1)
方法二:适合大规模数据集(高效优化)
如果你的数据量很大,上面的方法会因为每次遍历整个df2而变慢。可以先对df2的时间排序,然后用二分查找快速定位最近的时间,效率会提升很多:
# 先对df2按时间排序 df2_sorted = df2.sort_values('B_datetime').reset_index(drop=True) sorted_times = df2_sorted['B_datetime'] def get_closest_time_fast(row): current_time = row['A_datetime'] # 用二分查找找到插入位置 pos = sorted_times.searchsorted(current_time) # 处理边界情况:如果是第一个时间点,直接取第一个;如果是最后一个,取最后一个 if pos == 0: closest_idx = 0 elif pos == len(sorted_times): closest_idx = len(sorted_times) - 1 else: # 比较前后两个时间的差值,选更近的那个 time_before = sorted_times.iloc[pos-1] time_after = sorted_times.iloc[pos] if (current_time - time_before) < (time_after - current_time): closest_idx = pos - 1 else: closest_idx = pos return pd.Series( [df2_sorted.loc[closest_idx, 'B'], sorted_times.iloc[closest_idx]], index=['closest_B', 'closest_B_datetime'] ) # 合并结果到df1 df1 = pd.concat([df1, df1.apply(get_closest_time_fast, axis=1)], axis=1)
最终效果
运行后,df1会新增两列:
closest_B:df2中匹配到的原始时间字符串;closest_B_datetime:对应的datetime格式时间。
比如df1里第一个时间戳1499503900转换后是2017-07-08 05:31:40,匹配到的最近时间就是df2里的2017-07-03T10:20:46.333Z。
内容的提问来源于stack exchange,提问作者emily.mi
相关产品推荐
相关产品推荐

