大熊猫cumsum有条件产品的滞后价值?

时间:2014-09-06 14:54:42

标签: python numpy pandas

我试图得到一个累积和,根据另一个变量的乘积和总和的滞后值而变化(听起来有点像数学乱码,我知道......请耐心等待我)

以下是示例设置:

import pandas as pd
df = pd.DataFrame([1,1,1.004878,1,1.043394],columns=['xx'])
df['n'] = 1000000.0

汇总到:

       xx        n
0  1.000000  1000000
1  1.000000  1000000
2  1.004878  1000000
3  1.000000  1000000
4  1.043394  1000000

现在,我们需要迭代地将xx乘以n的滞后值,然后取这个值的累积和:

cs = pd.Series([0.0] * len(df))
cs[0] = df.ix[0]['n']
for i,e in enumerate(df.iterrows()):
    if i == 0: continue
    cs[i] = df.ix[i]['xx'] * cs[(i - 1)]

这会产生以下结果:

0    1000000.000000
1    1000000.000000
2    1004878.000000
3    1004878.000000
4    1048483.675932
dtype: float64

问题:有没有办法在pandas / numpy中执行此操作,不需要迭代每一行?如果没有,当您被迫迭代时,是否有任何优化代码的技巧如上所述?在这种情况下,创意制作的索引可以提供帮助吗?在多个数据集中,性能是一个涉及10000多行的问题。

2 个答案:

答案 0 :(得分:4)

首先,你的for循环可以简化为:

for i in xrange(1, len(df)):
    cs[i] = df.ix[i]['xx'] * cs[(i - 1)]

(更多数学胡言乱语) cs[1:]中的每个项目都是df['xx']中所有之前项目(累积产品)乘以n df列中第一项的乘积}}

>>> df
         xx        n
0  1.000000  1000000
1  1.000000  1000000
2  1.004878  1000000
3  1.000000  1000000
4  1.043394  1000000
>>> a = df['xx']
>>> a
0    1.000000
1    1.000000
2    1.004878
3    1.000000
4    1.043394
Name: xx, dtype: float64
>>> a = a.cumprod()
>>> a
0    1.000000
1    1.000000
2    1.004878
3    1.004878
4    1.048484
Name: xx, dtype: float64
>>> a = a * df['n'][0]
>>> a
0    1000000.000000
1    1000000.000000
2    1004878.000000
3    1004878.000000
4    1048483.675932
Name: xx, dtype: float64
>>> np.all(a == cs)
True
>>> 

a = df['xx'].cumprod() * df['n'][0]

这不是一招。 这仅适用,因为df['xx'][0]为1.如果是任何其他值,并且cs[0] = df.ix[0]['n']不仅仅是快捷方式,那么cumprod将无效。

扩展cs的每个项目

cs[0] = df['n'][0]
cs[1] = df['xx'][1] * df['n'][0]
cs[2] = df['xx'][2] * df['xx'][1] * df['n'][0]
cs[3] = df['xx'][3] * df['xx'][2] * df['xx'][1] * df['n'][0]
cs[4] = df['xx'][4] * df['xx'][3] * df['xx'][2] * df['xx'][1] * df['n'][0]

由于df['xx'][0]等于1,df['xx'][0] * df['n'][0] == df['n'][0]则等于:

cs[0] = df['xx'][0] * df['n'][0]
cs[1] = df['xx'][1] * df['xx'][0] * df['n'][0]
cs[2] = df['xx'][2] * df['xx'][1] * df['xx'][0] * df['n'][0]
cs[3] = df['xx'][3] * df['xx'][2] * df['xx'][1] * df['xx'][0] * df['n'][0]
cs[4] = df['xx'][4] * df['xx'][3] * df['xx'][2] * df['xx'][1] * df['xx'][0] * df['n'][0]

如果您稍微改变问题条件,在每次迭代后我需要减去最后一次计算的n值的0.05%(在下一次迭代之前),cumprod是否仍然有效?

如果您进行了项目扩展练习,您应该已经看到新条件会导致乘以缩放因子数组的累积乘积。两种方法 - 都会导致循环中执行的计算出现一些小的浮点错误。同样,您需要将df['xx']中的第一项视为一个。

for i in xrange(1, len(df)):
    cs[i] = df.ix[i]['xx'] * (.9995 * cs[(i - 1)])

>>> k
array([ 1.    ,  0.9995,  0.9995,  0.9995,  0.9995])
>>> z = df['xx'] * k
>>> z
0    1.000000
1    0.999500
2    1.004376
3    0.999500
4    1.042872
Name: xx, dtype: float64
>>> z = z.cumprod() * df['n'][0]
>>> cs - z
0    0.000000e+00
1    0.000000e+00
2    0.000000e+00
3    0.000000e+00
4   -1.164153e-10
dtype: float64
>>> 
>>> z = df['xx'].cumprod() * df['n'][0]
>>> z *= k.cumprod()
>>> cs - z
0    0.000000e+00
1    0.000000e+00
2   -1.164153e-10
3    0.000000e+00
4    0.000000e+00
dtype: float64
>>> 

答案 1 :(得分:1)

我不确定我是否理解'n'应该做什么(总是= 1,000,000?),但是将上面的结果与cumprod相匹配非常简单:

In [60]: df.xx.cumprod() * 1e6

Out[60]: 0    1000000.000000
         1    1000000.000000
         2    1004878.000000
         3    1004878.000000
         4    1048483.675932