我试图得到一个累积和,根据另一个变量的乘积和总和的滞后值而变化(听起来有点像数学乱码,我知道......请耐心等待我)
以下是示例设置:
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多行的问题。
答案 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