2012-09-07 11 views
12

kdb + tiene una función aj que generalmente se usa para unir tablas a lo largo de las columnas de tiempo.KDB + como asof join para datos de series temporales en pandas?

Aquí hay un ejemplo en el que tengo tablas de comercio y cotización y obtengo la cotización vigente para cada operación.

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 

¿Cómo puedo hacer la misma operación usando pandas? Estoy trabajando con marcos de datos comerciales y de cotización donde el índice es 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 

veo que tiene una función de pandas ASOF pero que no está definido en la trama de datos, sólo en la Serie del objeto. Supongo que uno podría recorrer cada una de las Series y alinearlas una por una, pero me pregunto si hay una mejor manera.

+1

esto también se llama * rolling join * – jangorecki

Respuesta

8

Como usted ha mencionado en la pregunta, bucle a través de cada columna debe trabajar para usted:

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

potencialmente Podríamos crear una versión más rápida NaN-ingenua de DataFrame.asof para hacer todas las columnas de una sola vez. Pero por ahora, creo que esta es la forma más directa.

+0

Gracias. Estoy tomando este enfoque por ahora. ¡Pero una versión ingenua de NaN sería muy bienvenida! – signalseeker

+1

https://gist.github.com/3686236 – signalseeker

13

escribí una función bajo-anunciada ordered_merge hace algún tiempo:

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 

Podría ser fácil (bueno, para alguien que esté familiarizado con el código) extendido a ser un "join izquierda" imitando KDB. Me doy cuenta en este caso que el llenado progresivo de los datos comerciales no es apropiado; solo ilustrando la función.

+1

Gracias, esto es muy bueno saberlo. Esto es esencialmente uj (http://code.kx.com/wiki/Reference/uj) en KDB !. Para la funcionalidad aj, voy con el enfoque de Chang pero planeo tomar una puñalada seria del código más tarde. – signalseeker

+1

¿Podría ser generalizado el caso en el que el marco de datos contiene muchas Series juntas, por ejemplo, si los datos, además de las marcas de tiempo, también tenían una columna de identificación de stock? (Así podemos tener miles de grupos, y cada uno de ellos es una Serie). Sospecho que necesitaremos una mezcla de 'groupby()' y 'ordered_merge', pero estoy luchando sobre cómo hacerlo ... De seguro, sería un error simplemente' ffill' en el orden general de la dataframe (no quiero que un grupo se derrame en el próximo grupo en virtud del llenado directo). –

Cuestiones relacionadas