KDB+ like asof 加入熊猫中的时间序列数据?

Posted

技术标签:

【中文标题】KDB+ like asof 加入熊猫中的时间序列数据?【英文标题】:KDB+ like asof join for timeseries data in pandas? 【发布时间】:2012-09-01 14:01:22 【问题描述】:

kdb+ 有一个aj 函数,通常用于沿时间列连接表。

这是一个示例,其中我有交易和报价表,并且我获得了每笔交易的现行报价。

q)5# t
time         sym  price size 
-----------------------------
09:30:00.439 NVDA 13.42 60511
09:30:00.439 NVDA 13.42 60511
09:30:02.332 NVDA 13.42 100  
09:30:02.332 NVDA 13.42 100  
09:30:02.333 NVDA 13.41 100  

q)5# q
time         sym  bid   ask   bsize asize
-----------------------------------------
09:30:00.026 NVDA 13.34 13.44 3     16   
09:30:00.043 NVDA 13.34 13.44 3     17   
09:30:00.121 NVDA 13.36 13.65 1     10   
09:30:00.386 NVDA 13.36 13.52 21    1    
09:30:00.440 NVDA 13.4  13.44 15    17

q)5# aj[`time; t; q]
time         sym  price size  bid   ask   bsize asize
-----------------------------------------------------
09:30:00.439 NVDA 13.42 60511 13.36 13.52 21    1    
09:30:00.439 NVDA 13.42 60511 13.36 13.52 21    1    
09:30:02.332 NVDA 13.42 100   13.34 13.61 1     1    
09:30:02.332 NVDA 13.42 100   13.34 13.61 1     1    
09:30:02.333 NVDA 13.41 100   13.34 13.51 1     1  

如何使用 pandas 执行相同的操作?我正在使用索引为 datetime64 的交易和报价数据框。

In [55]: quotes.head()
Out[55]: 
                              bid    ask  bsize  asize
2012-09-06 09:30:00.026000  13.34  13.44      3     16
2012-09-06 09:30:00.043000  13.34  13.44      3     17
2012-09-06 09:30:00.121000  13.36  13.65      1     10
2012-09-06 09:30:00.386000  13.36  13.52     21      1
2012-09-06 09:30:00.440000  13.40  13.44     15     17

In [56]: trades.head()
Out[56]: 
                            price   size
2012-09-06 09:30:00.439000  13.42  60511
2012-09-06 09:30:00.439000  13.42  60511
2012-09-06 09:30:02.332000  13.42    100
2012-09-06 09:30:02.332000  13.42    100
2012-09-06 09:30:02.333000  13.41    100

我看到 pandas 有一个 asof 函数,但它没有在 DataFrame 上定义,只在 Series 对象上。我想可以循环遍历每个系列并一一对齐,但我想知道是否有更好的方法?

【问题讨论】:

这也叫滚动加入 【参考方案1】:

正如您在问题中提到的,遍历每一列应该适合您:

df1.apply(lambda x: x.asof(df2.index))

我们可能会创建一个更快的 NaN-naive 版本的 DataFrame.asof 来一次性完成所有列。但就目前而言,我认为这是最直接的方法。

【讨论】:

谢谢。我现在正在采用这种方法。但是非常欢迎使用 NaN-naive 版本!【参考方案2】:

前段时间我写了一个广告不足的ordered_merge函数:

In [27]: quotes
Out[27]: 
                        time    bid    ask  bsize  asize
0 2012-09-06 09:30:00.026000  13.34  13.44      3     16
1 2012-09-06 09:30:00.043000  13.34  13.44      3     17
2 2012-09-06 09:30:00.121000  13.36  13.65      1     10
3 2012-09-06 09:30:00.386000  13.36  13.52     21      1
4 2012-09-06 09:30:00.440000  13.40  13.44     15     17

In [28]: trades
Out[28]: 
                        time  price   size
0 2012-09-06 09:30:00.439000  13.42  60511
1 2012-09-06 09:30:00.439000  13.42  60511
2 2012-09-06 09:30:02.332000  13.42    100
3 2012-09-06 09:30:02.332000  13.42    100
4 2012-09-06 09:30:02.333000  13.41    100

In [29]: ordered_merge(quotes, trades)
Out[29]: 
                        time    bid    ask  bsize  asize  price   size
0 2012-09-06 09:30:00.026000  13.34  13.44      3     16    NaN    NaN
1 2012-09-06 09:30:00.043000  13.34  13.44      3     17    NaN    NaN
2 2012-09-06 09:30:00.121000  13.36  13.65      1     10    NaN    NaN
3 2012-09-06 09:30:00.386000  13.36  13.52     21      1    NaN    NaN
4 2012-09-06 09:30:00.439000    NaN    NaN    NaN    NaN  13.42  60511
5 2012-09-06 09:30:00.439000    NaN    NaN    NaN    NaN  13.42  60511
6 2012-09-06 09:30:00.440000  13.40  13.44     15     17    NaN    NaN
7 2012-09-06 09:30:02.332000    NaN    NaN    NaN    NaN  13.42    100
8 2012-09-06 09:30:02.332000    NaN    NaN    NaN    NaN  13.42    100
9 2012-09-06 09:30:02.333000    NaN    NaN    NaN    NaN  13.41    100

In [32]: ordered_merge(quotes, trades, fill_method='ffill')
Out[32]: 
                        time    bid    ask  bsize  asize  price   size
0 2012-09-06 09:30:00.026000  13.34  13.44      3     16    NaN    NaN
1 2012-09-06 09:30:00.043000  13.34  13.44      3     17    NaN    NaN
2 2012-09-06 09:30:00.121000  13.36  13.65      1     10    NaN    NaN
3 2012-09-06 09:30:00.386000  13.36  13.52     21      1    NaN    NaN
4 2012-09-06 09:30:00.439000  13.36  13.52     21      1  13.42  60511
5 2012-09-06 09:30:00.439000  13.36  13.52     21      1  13.42  60511
6 2012-09-06 09:30:00.440000  13.40  13.44     15     17  13.42  60511
7 2012-09-06 09:30:02.332000  13.40  13.44     15     17  13.42    100
8 2012-09-06 09:30:02.332000  13.40  13.44     15     17  13.42    100
9 2012-09-06 09:30:02.333000  13.40  13.44     15     17  13.41    100

它可以很容易(好吧,对于熟悉代码的人来说)扩展为模仿 KDB 的“左连接”。我意识到在这种情况下,向前填充交易数据是不合适的;只是说明功能。

【讨论】:

谢谢,很高兴知道这一点。这本质上是 KDB 中的 uj (code.kx.com/wiki/Reference/uj)!。对于 aj 功能,我将采用 Chang 的方法,但我计划稍后认真研究代码。 这是否可以概括为数据框包含许多系列的情况,例如,如果数据除了时间戳之外还有一个股票 ID 列? (因此我们可能有数千个组,每个组都是一个系列)。我怀疑我们需要混合使用groupby()ordered_merge,但我正在为如何做到这一点而苦苦挣扎......当然,在数据帧的整体顺序上简单地使用ffill 是错误的(我不希望一个组由于前向填充而溢出到下一个组中)。【参考方案3】:

pandas 0.19 has introduced an asof join:

pd.merge_asof(trades, quotes, on='time')

语义与 q/kdb+ 中的功能非常相似。

【讨论】:

以上是关于KDB+ like asof 加入熊猫中的时间序列数据?的主要内容,如果未能解决你的问题,请参考以下文章

加入带有日期范围的熊猫时间序列

熊猫 - 按时间接近加入

不平等加入熊猫?

Kdb+ A股数据库

按值加入两个熊猫系列[重复]

SQL在列上加入LIKE另一列[重复]