我想在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
然后迭代它:
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中用较少的努力可以做到这一点,那也会很好!
提前多多感谢!
答案 0 :(得分:0)
根据问题的属性,您可以使用np.where
查找超出级别的位置并对时间序列进行分类。
这里的一大缺点是np.where
将为您提供时间序列高于value[i] + step
等的每个索引,这可能会将线性时间算法转换为二次时间算法。根据您将要处理的问题的大小,我希望您在前因中获得很多收益;你甚至可能最终得到二次时间的numpy解决方案。
从四处寻找,相当于np.where
的“找到第一个索引”仍然是一个请求的功能。