2012-09-07 12 views
12

kdb + ma funkcję aj, która jest zwykle używana do łączenia tabel w kolumnach czasu.KDB + jak asof dołączyć do danych timeseries w pandy?

Oto przykład, gdzie mam tabele transakcji i ofert i otrzymuję dominującą ofertę dla każdego handlu.

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 

Jak wykonać tę samą operację za pomocą pand? Pracuję z ramkami danych handlu i cytowania, gdzie indeks jest 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 

Widzę, że pandy mają funkcję asofi, ale nie jest to zdefiniowane w DataFrame, tylko w obiekcie Series. Sądzę, że można było przechodzić przez każdą z serii i dopasowywać je jeden po drugim, ale zastanawiam się, czy istnieje lepszy sposób?

+1

to jest również nazywane * walcowaniem łączenia * – jangorecki

Odpowiedz

8

Jak wspomniano w pytaniu, przelotowego każdej kolumny powinny pracować dla Ciebie:

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

Możemy potencjalnie stworzyć szybciej NaN-naiwną wersję DataFrame.asof zrobić wszystkie kolumny w jednym ujęciu. Ale na razie myślę, że jest to najprostszy sposób.

+0

Dzięki. Obecnie stosuję to podejście. Ale naiwna wersja NaN byłaby bardzo pożądana! – signalseeker

+1

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

13

napisałem pod reklamowanych ordered_merge funkcję jakiś czas temu:

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 

To może być łatwo (dobrze, dla kogoś, kto jest zaznajomiony z kodem) rozszerzyła się „left join” naśladując KDB. W tym przypadku zdaję sobie sprawę, że przekazywanie danych handlowych nie jest właściwe; tylko ilustruję funkcję.

+1

Dzięki, bardzo dobrze jest wiedzieć. Jest to w zasadzie uj (http://code.kx.com/wiki/Reference/uj) w KDB !. Dla funkcji aj idę z podejściem Changa, ale planuję poważnie zaatakować kod później. – signalseeker

+1

Czy można uogólnić przypadek, w którym ramka danych zawiera wiele serii razem, na przykład jeśli dane, oprócz znaczników czasu, również miały kolumnę ID akcji? (Możemy więc mieć tysiące grup, a każda z nich jest serią). Podejrzewam, że potrzebujemy mieszanki 'groupby()' i 'ordered_merge', ale walczę o to, jak to zrobić ... Na pewno byłoby błędem po prostu" ffill "na ogólnej kolejności Dataframe (nie chcę, aby grupa przeniosła się do następnej grupy dzięki wypełnieniu do przodu). –

Powiązane problemy