2014-09-06 48 views
3

我试图得到一个累计和,根据另一个变量的产品和总和的滞后值变化(听起来有点像数学乱码,我知道..请耐心等待)熊猫cumsum与滞后值的条件产品?

这里是例如设置:

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 

现在,我们需要的n,反复的滞后值乘以xx,然后采取累积这个值的总和:

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 

问:有没有办法在大熊猫做到这一点/不需要遍历每个行numpy的?如果不是,当你被迫迭代时,是否有任何技巧来优化上述代码?在这种情况下,可以创造性地制作索引帮助吗?在多个数据集中,性能是10000行以上的问题。

+0

使用[SHIFT](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.shift.html) – U2EF1 2014-09-06 18:59:13

回答

4

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

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

(更多的数学乱码)cs[1:]每个项目都是以前我的产品在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] 

此所述n列乘以该第一个项目中df['xx'](累积产物)TEMS不是特技。 这只适用于因为df['xx'][0]是1.如果它是任何其他值,AND 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]等于再一个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 
>>> 
+0

感谢您对这里的非常详尽的解释。如果我在每次迭代后稍微改变问题条件,我需要减去最后一次计算的n值的0.05%(在下一次迭代之前),cumprod仍然有效吗? – bazel 2014-09-06 23:58:53

+0

我不确定我是否理解新的计算。它是'''cs [i] = df.ix [i] ['xx'] *(.995 * cs [(i - 1)])'''?减去.05%与缩小.995相同。看看你是否可以使用这个因子来扩展每个cs项目(像我上面所做的那样) - 手动遍历迭代*,看看''''''''''''''''''''''''''''''''''''''然后测试它两种方法 - 迭代和'''cumprod'''来查看结果是否相同。 – wwii 2014-09-07 00:21:18

+0

太好了,再次感谢您提供有用的建议 – bazel 2014-09-07 05:15:18

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