use*_*348 5 python numpy r vectorization pandas
我想在大熊猫的DataFrame(可以被认为是一个系列)上做一个"奇怪的"计算.DataFrame必须被视为时间序列或类似的(元素的顺序很重要).
看向前在元素[I:],并指定为值[I]的一个"类":
我知道这听起来很疯狂.想象一下随机步行+ 1/-1步.像这样的序列:
我通过定义一个函数解决了它的"经典"(也许不是那么pythonic)方式:
import numpy as np
import pandas as pd
def FindClass(inarr, i=0, step=0.001, rr=2):
j = 0
foundClass = None
while i+j < len(inarr) - 1:
j += 1
if inarr[i+j] >= inarr[i] + step:
direction = 1
break
if inarr[i+j] <= inarr[i] - step:
direction = -1
break
while i+j < len(inarr)-1:
j += 1
if direction == 1 and inarr[i+j] >= inarr[i] + (step * rr):
foundClass = 1
break
elif direction == 1 and inarr[i+j] <= inarr[i] - step:
foundClass = 0
break
elif direction == -1 and inarr[i+j] <= inarr[i] - (step * rr):
foundClass = -1
break
elif direction == -1 and inarr[i+j] >= inarr[i] + step:
foundClass = 0
break
if foundClass is None:
foundClass = np.nan
return foundClass
Run Code Online (Sandbox Code Playgroud)
然后迭代它:
if __name__ == "__main__":
steps = np.random.randint(-1, 2, size= 10000)
randomwalk = steps.cumsum(0)
rc = pd.DataFrame({'rw':randomwalk, 'result': np.nan})
for c in range(0, len(rc)-1):
rc.result[c] = FindClass(rc.rw, i=c, step=1)
print rc
Run Code Online (Sandbox Code Playgroud)
在我的笔记本电脑上(以及运行python 2.7),我得到的分析对于10000个元素的系列来说并不"太糟糕":
python -m cProfile -s cumulative fbmk.py
<class 'pandas.core.frame.DataFrame'>
Int64Index: 10000 entries, 0 to 9999
Data columns (total 2 columns):
result 9996 non-null values
rw 10000 non-null values
dtypes: float64(1), int32(1)
932265 function calls (929764 primitive calls) in 2.643 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.106 0.106 2.646 2.646 fbmk.py:1(<module>)
9999 0.549 0.000 1.226 0.000 fbmk.py:4(FindClass)
158062 0.222 0.000 0.665 0.000 series.py:616(__getitem__)
2 0.029 0.014 0.561 0.281 __init__.py:3(<module>)
158062 0.226 0.000 0.443 0.000 index.py:718(get_value)
19998 0.070 0.000 0.442 0.000 frame.py:2082(__getattr__)
19998 0.111 0.000 0.331 0.000 frame.py:1986(__getitem__)
Run Code Online (Sandbox Code Playgroud)
问题是:
有没有人看到有可能以提高性能的方式在pandas/numpy中矢量化这个函数?
如果在R中用较少的努力可以做到这一点,那也会很好!
非常感谢提前!
根据问题的属性,您可以用来np.where查找级别交叉的位置并对时间序列进行分类。
这里最大的缺点是np.where将为您提供时间序列高于value[i] + step等的每个索引,这可能会将线性时间算法变成二次时间算法。根据您要处理的问题的大小,我预计您会在前置因素中获益匪浅;你甚至可能最终得到二次时间 numpy 解决方案。
经过摸索,“查找第一个索引”等效项np.where仍然是一个请求的功能。