如何在非相等时间值上加速连接大型数据集



我有2个大数据框df1df2,它们都有一个列time。我想加入这两张桌子。然而,可能并不总是完全匹配。在这种情况下,我想加入这样,我以一种有效的方式获取df1的时间值之前发生的df2的最新时间值。

例如,给定表

df1
Time             | val_1
------------------------
1/1/1980 1:00:00 | 1
1/1/1980 2:00:00 | 2
1/1/1980 3:00:00 | 3
1/1/1980 4:00:00 | 4
df2
time             | val_2
------------------------
1/1/1980 1:00:00 | 5
1/1/1980 1:59:59 | 6
1/1/1980 3:00:01 | 7
1/1/1980 3:30:30 | 8

最终表应该是

time             | val_1 | val_2
--------------------------------
1/1/1980 1:00:00 | 1     | 5
1/1/1980 2:00:00 | 2     | 6
1/1/1980 3:00:00 | 3     | 6
1/1/1980 4:00:00 | 4     | 8

我正在执行此操作,但运行时间太高

def prevrow(t):
return df2.iloc[df2['time'].apply(lambda x: t - x if t >= x else np.nan).idxmin()]
pd.concat([df1,df1['Time'].apply(prevrow)], axis=1)

如何加快速度?

我们可以尝试用merge_asof代替:

# df1 = df1.rename(columns={'Time': 'time'})
new_df = pd.merge_asof(df1, df2, on='time', direction='backward')

*注意direction='backward'是默认的方向,所以不需要指定,但是,这是我们正在寻找的匹配方向。

new_df:

time  val_1  val_2
0 1980-01-01 01:00:00      1      5
1 1980-01-01 02:00:00      2      6
2 1980-01-01 03:00:00      3      6
3 1980-01-01 04:00:00      4      8

需要注意的是time列必须在两个dataframe中排序,这可以通过sort_values

来完成(如果还没有)
# df1 = df1.rename(columns={'Time': 'time'})
new_df = pd.merge_asof(df1.sort_values('time'),
df2.sort_values('time'), 
on='time')

一些计时信息通过%timeit:

原始的方法:

def prevrow(t):
return df2.iloc[df2['time'].apply(lambda x: t - x if t >= x else np.nan).idxmin()]
%timeit pd.concat([df1,df1['time'].apply(prevrow)], axis=1)
2.29 ms ± 172 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

不排序的merge_asof:

%timeit pd.merge_asof(df1, df2, on='time')
1.13 ms ± 50.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

merge_asofwith sorting:

%timeit pd.merge_asof(df1.sort_values('time'), df2.sort_values('time'), on='time')
1.46 ms ± 27.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

数据和导入:

import pandas as pd
df1 = pd.DataFrame({
'time': pd.to_datetime(['1/1/1980 1:00:00', '1/1/1980 2:00:00',
'1/1/1980 3:00:00', '1/1/1980 4:00:00']),
'val_1': [1, 2, 3, 4]
})
df2 = pd.DataFrame({
'time': pd.to_datetime(['1/1/1980 1:00:00', '1/1/1980 1:59:59',
'1/1/1980 3:00:01', '1/1/1980 3:30:30']),
'val_2': [5, 6, 7, 8]
})

相关内容

  • 没有找到相关文章

最新更新