我尝试在网站上搜索一个很好的方法来实现这个(尝试了一些binning和时间序列的想法),但仍然找不到合适的灵魂。
这是问题
我有两个数据帧:
index name time price
1, AAA, 11:37:09.359479, 58.480000,10
2, ABC, 11:37:15.403268, 0.5000000,3
3, ABB, 11:37:15.491515, 0.4500000,2
4, AAA, 11:37:15.604864, 0.5000000,1
5, ABC, 11:37:16.628756, 0.1800000,20
6, ABD, 11:37:21.083105, 0.8000000,7
7, AAA, 11:37:21.423480, 79.030000,10
index name time price
1, ABB, 11:37:15.491525, 0.4500000,2
2, AAA, 11:37:15.604884, 0.5000000,1
3, ABC, 11:37:16.628796, 0.1800000,20
正如您所看到的,数据帧1中的索引3,4,5具有来自dataftame 2的相应索引1,2,3
我需要将这些数据帧合并到一个'time'列中,以便对于来自数据帧1的记录3,4,5来自数据帧2的1,2,3在右边。
这应该是结果:
index_x name_x time_x price_x name_y time_y price_y
1, AAA, 11:37:09.359479, 58.480000,10 Nan ...
2, ABC, 11:37:15.403268, 0.5000000,3 Nan ..
3, ABB, 11:37:15.491515, 0.4500000,2 ABB, 11:37:15.491525, 0.4500000,2
4, AAA, 11:37:15.604864, 0.5000000,1 AAA, 11:37:15.604884, 0.5000000,1
5, ABC, 11:37:16.628756, 0.1800000,20 ABC, 11:37:16.628796, 0.1800000,20
6, ABD, 11:37:21.083105, 0.8000000,7 Nan ..
7, AAA, 11:37:21.423480, 79.030000,10 Nan ..
我有麻烦,因为时间不完全一样(看最后2微秒)。有没有一种很好的方法来合并它的方式来按时合并这些不完全匹配,但给出一些匹配的阈值可能?每条记录也应该只有不超过一个匹配。
如果清楚,请告诉我。
非常感谢你!
答案 0 :(得分:2)
不幸的是这些"关闭比赛"在熊猫中很少有一个超级简单的解决方案,但这并不是太糟糕。您可以做的是从@ CharlieHaley的解决方案开始,然后将其置于一个循环中,以便您可以进行最精确的匹配并丢弃不太精确的匹配。
当然,这仍然会让您决定使用哪些精度级别(在< decimal_range'中指定)。我开始在7的范围内保持输出简洁,但是你想要从1开始,然后决定你想要多高,因为更高的数字允许不那么精确的匹配。
(注意:我假设你的初始数据帧是' df1'和' df2'而且' time'是一个字符串,如果不是你需要先将其转换为字符串。)
decimal_range = range(7,9)
df1 = df1.reset_index() # this creates column 'index' later used for
# dropping duplicates. depending on your
# goals, may want to do for df2 instead of df1
df3=pd.DataFrame()
for i in decimal_range:
df1['time2'] = df1['time'].str[:-i]
df2['time2'] = df2['time'].str[:-i]
df3 = df3.append( df1.merge(df2,on=['name','time2'], how='inner'), )
df4 = df3.drop_duplicates(subset=['index','name'])
显示中间输出可能会更清楚。在i=7
合并时,有3个匹配,但在i=8
有4个匹配。 ' time2'列显示用于匹配的精度。
df3
index name time_x price_x time2 time_y price_y
0 2 ABB 11:37:15.491515 0.45 11:37:15 11:37:15.491525 0.45
1 3 AAA 11:37:15.604864 0.50 11:37:15 11:37:15.604884 0.50
2 4 ABC 11:37:16.628756 0.18 11:37:16 11:37:16.628796 0.18
0 1 ABC 11:37:15.403268 0.50 11:37:1 11:37:16.628796 0.18
1 4 ABC 11:37:16.628756 0.18 11:37:1 11:37:16.628796 0.18
2 2 ABB 11:37:15.491515 0.45 11:37:1 11:37:15.491525 0.45
3 3 AAA 11:37:15.604864 0.50 11:37:1 11:37:15.604884 0.50
累积匹配后,只需删除重复项以保持更精确的匹配。
df4
index name time_x price_x time2 time_y price_y
0 2 ABB 11:37:15.491515 0.45 11:37:15 11:37:15.491525 0.45
1 3 AAA 11:37:15.604864 0.50 11:37:15 11:37:15.604884 0.50
2 4 ABC 11:37:16.628756 0.18 11:37:16 11:37:16.628796 0.18
0 1 ABC 11:37:15.403268 0.50 11:37:1 11:37:16.628796 0.18
答案 1 :(得分:0)
我最终做的是将我的数据帧拆分为相等的bin,然后将它们合并到bin ID上。
这样做的一个缺点是,我只能这样做才能实现共同'共享'这两个数据帧中的时间间隔(对于第一个数据帧中的索引3,4,5)。
同一个bin中也可能有多条记录,在这种情况下我只是使用双方的最后一条记录进行合并。
所以我这样做(我的数据框名称是onTrade1和onTrade2):
commonFirstTime = max (onTrade1['exchangeTime'].min(), onTrade2['exchangeTime'].min())
commonLastTime = min (onTrade1['exchangeTime'].max(), onTrade2['exchangeTime'].max())
bins = numpy.linspace(commonFirstTime, commonLastTime, ((commonLastTime - commonFirstTime) / 1000))
groups1 = onTrade1.groupby(numpy.digitize(onTrade1['exchangeTime'], bins))
groups2 = onTrade2.groupby(numpy.digitize(onTrade2['exchangeTime'], bins))
然后我可以简单地将groups1与groups2合并到公共索引上。