我想对熊猫中的DataFrame(可以被认为是一个系列)进行一次"奇怪"的计算。DataFrame必须被视为时间序列或类似序列(元素的顺序很重要)。
- 给定索引[i]处的值(值[i])
- 给定一个步长(例如1)[整数或实数]
- 给定乘数rr(例如2)[整数或实数]
向前看元素[i:],并为值[i]分配一个"类":
- +1如果随后的值在达到值[i]-step之前达到值[i]+step*rr的水平
- -1如果随后的值在达到值[i]+step之前达到值[i]-step*rr的级别
- 0(即,当随后的值触摸值[i]-step,然后触摸值[i]+step,反之亦然)
我知道这听起来很疯狂。想象一下一次随机行走,每走+1/-1步。类似的序列
- 0,1,2将分配给类+1(也可以是0,1、0、0、1,1,0、1、1,2)
- 0、-1、-2将被分配给类-1(它也可以是0、-1,0、0、1、-1、-1、-2)
- 0、+1、0、-1或0、-1、0、0、-1、0、1等将是类0
我已经通过定义一个函数以"经典"(也许不是蟒蛇)的方式解决了这个问题:
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
然后迭代:
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
在我的笔记本电脑(运行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__)
问题是:
是否有人认为可以在pandas/numpy中对该函数进行矢量化,从而提高性能
如果这件事在R上花更少的努力是可行的,那也太好了!
提前感谢!
根据问题的属性,可以使用np.where
来查找跨越级别的位置并对时间序列进行分类。
这里最大的缺点是np.where
会给你时间序列高于value[i] + step
的每个指数,等等,这可能会把线性时间算法变成二次时间算法。根据你将要处理的问题的大小,我预计你会在预测器中获得很多好处;你甚至可能最终得到二次时间numpy解。
仔细观察,np.where
的"查找第一个索引"功能仍然是一个需要的功能。