加速自定义聚合函数
Speed up custom aggregation functions
我有一个非常简单的设置:pandas 数据帧 df 中的市场数据(报价),如下所示:
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
现在我使用pandas.groupy来汇总经期
g=df.groupby('period')
很容易按时段获取最低和最高价格,例如
import numpy as np
res=g.agg({'ask': [np.amax, np.amin]})
这也相当快。现在,我还想要每个时期的第一个和最后一个价格。这是麻烦开始的地方。我当然可以:
res=g.agg({'ask': lambda x: x[0]})
它基本上可以工作,但对于大型数据集来说速度非常慢。基本上,Python 函数调用的调用开销非常大。
有谁知道类似于 np.amax 的 numpy 函数,它将 return 组的第一个或最后一个元素?我找不到一个。 iloc[0] 没有用,因为它是一个对象的方法,因此,我不能将它作为函数传递给 g.agg,因为我在这个阶段没有对象(那是需要 lambda 做什么)。
现在,我并不懒惰,我尝试使用 cython 为自己做这件事。
import numpy as np
cimport numpy as np
cpdef double first(np.ndarray array_series):
return array_series[0]
但是 pandas 不会接受它作为聚合函数,因为它传递的是 pd.core.series-对象而不是 np.ndarray。 (没关系,一个派生自另一个,编译器无法识别。)
有谁知道如何编写接受 pandas 系列且没有 python 调用开销的 cython 函数?
IIUC 然后你可以做 first
和 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
另一种方法是简单地重新采样并使用 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
我有一个非常简单的设置:pandas 数据帧 df 中的市场数据(报价),如下所示:
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
现在我使用pandas.groupy来汇总经期
g=df.groupby('period')
很容易按时段获取最低和最高价格,例如
import numpy as np
res=g.agg({'ask': [np.amax, np.amin]})
这也相当快。现在,我还想要每个时期的第一个和最后一个价格。这是麻烦开始的地方。我当然可以:
res=g.agg({'ask': lambda x: x[0]})
它基本上可以工作,但对于大型数据集来说速度非常慢。基本上,Python 函数调用的调用开销非常大。
有谁知道类似于 np.amax 的 numpy 函数,它将 return 组的第一个或最后一个元素?我找不到一个。 iloc[0] 没有用,因为它是一个对象的方法,因此,我不能将它作为函数传递给 g.agg,因为我在这个阶段没有对象(那是需要 lambda 做什么)。
现在,我并不懒惰,我尝试使用 cython 为自己做这件事。
import numpy as np
cimport numpy as np
cpdef double first(np.ndarray array_series):
return array_series[0]
但是 pandas 不会接受它作为聚合函数,因为它传递的是 pd.core.series-对象而不是 np.ndarray。 (没关系,一个派生自另一个,编译器无法识别。)
有谁知道如何编写接受 pandas 系列且没有 python 调用开销的 cython 函数?
IIUC 然后你可以做 first
和 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
另一种方法是简单地重新采样并使用 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