2015-10-30 14 views
6

Mam bardzo prostą konfigurację: dane rynkowe (kleszcze) w Pandy dataframe df tak:przyspieszyć niestandardowe funkcje agregujące

index period ask bid 
00:00:00.126 42125 112.118 112.117 
00:00:00.228 42125 112.120 112.117 
00:00:00.329 42125 112.121 112.120 
00:00:00.380 42125 112.123 112.120 
00:00:00.432 42125 112.124 112.121 
00:00:00.535 41126 112.124 112.121 
00:00:00.586 41126 112.122 112.121 
00:00:00.687 41126 112.124 112.121 
00:00:01.198 41126 112.124 112.120 
00:00:01.737 41126 112.124 112.121 
00:00:02.243 41126 112.123 112.121 

Teraz używam pandas.groupy okresów kruszywa

g=df.groupby('period') 

Łatwo jest uzyskać ceny minimalne i maksymalne według okresu, np

import numpy as np 
res=g.agg({'ask': [np.amax, np.amin]}) 

Jest to również stosunkowo szybki. Teraz chcę również pierwszą i ostatnią cenę za okres. Tu zaczyna się kłopot. Oczywiście, że mogę:

res=g.agg({'ask': lambda x: x[0]}) 

i to działa, ale jest strasznie powolne dla dużych zbiorów danych. Zasadniczo, obciążenie połączenia dla wywołania funkcji w Pythonie jest po prostu ogromne.

Czy ktoś wie o funkcji numpy analogicznej do np.amax, która zwróci pierwszy lub ostatni element grupy? Nie mogłem go znaleźć. iloc [0] nie rozwiązuje problemu, ponieważ jest metodą obiektu, a zatem nie mogę go przekazać jako funkcji g.agg, ponieważ nie mam obiektu na tym etapie (to jest to, lambda jest potrzebna).

Teraz nie jestem leniwy, a ja próbowałem zrobić to za siebie, używając cythonu.

import numpy as np 
cimport numpy as np 

cpdef double first(np.ndarray array_series): 
    return array_series[0] 

Ale pandy nie zaakceptuje to jako funkcję agregacji, ponieważ przechodzi pd.core.series-Object raczej niż np.ndarray. (Nieważne, jedno pochodzi od drugiego, kompilator tego nie rozpoznaje).

Czy ktoś wie, jak napisać funkcję cythonową, która akceptuje serię pand bez kosztu rozmowy Pythona?

+0

Czy próbowałeś 'df.groupby ('Okres') w pierwszej kolejności.() 'i' df.groupby ('okres'). last() '? – EdChum

+0

Dzięki, to dobra wskazówka. Działa, ale nie mogę przekazać funkcji first() do g.agg (...), czy mogę? Chciałbym to lepiej, ponieważ chciałbym zastosować wiele różnych funkcji agregacji naraz (amin, amax, first, ...). Będzie to obejście, aby go użyć, a następnie ręcznie zestawić mój ostateczny zestaw danych, jak sądzę. – user5507059

+0

Tak, możesz, zobacz moją odpowiedź – EdChum

Odpowiedz

3

IIUC wtedy można zrobić first i last:

In [270]: 
g=df.groupby('period') 
res=g.agg({'ask': [np.amax, np.amin, 'first', 'last']}) 
res 

Out[270]: 
      ask       
      amax  amin first  last 
period          
41126 112.124 112.122 112.124 112.123 
42125 112.124 112.118 112.118 112.124 
+0

Jesteś niesamowity. Dziękuję Ci!! – user5507059

+0

Ale idę o krok dalej. Co jeśli chcę niestandardową niestandardową funkcję agregacji. Czy mogę ją cytonizować? – user5507059

+0

prawdopodobnie, ale nie jestem ekspertem od cythonu – EdChum

1

Alternatywą jest po prostu resample i używać OHLC (open=first,close=last,high=max,low=min)

In [56]: df = DataFrame({'A' : np.arange(10), 'B' : pd.date_range('20130101',periods=5).tolist()*2}) 

In [57]: df 
Out[57]: 
    A   B 
0 0 2013-01-01 
1 1 2013-01-02 
2 2 2013-01-03 
3 3 2013-01-04 
4 4 2013-01-05 
5 5 2013-01-01 
6 6 2013-01-02 
7 7 2013-01-03 
8 8 2013-01-04 
9 9 2013-01-05 

In [58]: df.set_index('B').resample('D',how='ohlc') 
Out[58]: 
       A    
      open high low close 
B        
2013-01-01 0 5 0  5 
2013-01-02 1 6 1  6 
2013-01-03 2 7 2  7 
2013-01-04 3 8 3  8 
2013-01-05 4 9 4  9