我有两个数据帧,两个数据帧都包含一个不规则间隔的毫秒分辨率时间戳列。我的目标是匹配行,以便对于每个匹配的行,1)第一个时间戳总是小于或等于第二个时间戳,2)匹配的时间戳对于满足1)的所有时间戳对最接近。
有没有办法用pandas.merge做到这一点?
答案 0 :(得分:27)
merge()
无法进行此类加入,但您可以使用searchsorted()
:
创建一些随机时间戳:t1
,t2
,按升序排列:
import pandas as pd
import numpy as np
np.random.seed(0)
base = np.array(["2013-01-01 00:00:00"], "datetime64[ns]")
a = (np.random.rand(30)*1000000*1000).astype(np.int64)*1000000
t1 = base + a
t1.sort()
b = (np.random.rand(10)*1000000*1000).astype(np.int64)*1000000
t2 = base + b
t2.sort()
致电searchsorted()
为t1
中的每个值t2
寻找索引:
idx = np.searchsorted(t1, t2) - 1
mask = idx >= 0
df = pd.DataFrame({"t1":t1[idx][mask], "t2":t2[mask]})
这是输出:
t1 t2
0 2013-01-02 06:49:13.287000 2013-01-03 16:29:15.612000
1 2013-01-05 16:33:07.211000 2013-01-05 21:42:30.332000
2 2013-01-07 04:47:24.561000 2013-01-07 04:53:53.948000
3 2013-01-07 14:26:03.376000 2013-01-07 17:01:35.722000
4 2013-01-07 14:26:03.376000 2013-01-07 18:22:13.996000
5 2013-01-07 14:26:03.376000 2013-01-07 18:33:55.497000
6 2013-01-08 02:24:54.113000 2013-01-08 12:23:40.299000
7 2013-01-08 21:39:49.366000 2013-01-09 14:03:53.689000
8 2013-01-11 08:06:36.638000 2013-01-11 13:09:08.078000
要按图表查看此结果:
import pylab as pl
pl.figure(figsize=(18, 4))
pl.vlines(pd.Series(t1), 0, 1, colors="g", lw=1)
pl.vlines(df.t1, 0.3, 0.7, colors="r", lw=2)
pl.vlines(df.t2, 0.3, 0.7, colors="b", lw=2)
pl.margins(0.02)
输出:
绿线为t1
,蓝线为t2
,每t1
为t2
选择红线。
答案 1 :(得分:5)
Pandas现在具有merge_asof
功能,完全按照接受的答案进行描述。
答案 2 :(得分:4)
这是一种更简单,更通用的方法。
# data and signal are want we want to merge
keys = ['channel', 'timestamp'] # Could be simply ['timestamp']
index = data.loc[keys].set_index(keys).index # Make index from columns to merge on
padded = signal.reindex(index, method='pad') # Key step -- reindex with filling
joined = data.join(padded, on=keys) # Join to data if needed
答案 3 :(得分:3)
我使用了与HYRY不同的方式:
所有这些都可以写成几行:
{{1}}