矢量化前瞻性函数pandas数据帧



我想对熊猫中的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的"查找第一个索引"功能仍然是一个需要的功能。

最新更新