Python 累积收益函数
我有一个数据帧,如下所示:Python 累积收益函数,python,pandas,dataframe,finance,Python,Pandas,Dataframe,Finance,我有一个数据帧,如下所示: Index Return 2008-11-21 0.153419 2008-11-24 0.037421 2008-11-25 0.077500 计算最后一行所有列的累积回报的最佳方法是什么 预期结果如下: Index Return 2008-11-21 0.153419 2008-11-24 0.037421 2008-11-25 0.077500 Cumulative 0.289316 其中累积回报率计算
Index Return
2008-11-21 0.153419
2008-11-24 0.037421
2008-11-25 0.077500
计算最后一行所有列的累积回报的最佳方法是什么
预期结果如下:
Index Return
2008-11-21 0.153419
2008-11-24 0.037421
2008-11-25 0.077500
Cumulative 0.289316
其中累积回报率计算如下:
cumulative = (1 + return1) * (1 + return2) * (1 + return3) - 1
在pandas中执行此操作的最佳方法是什么?一个选项是只使用
减少
,尽管其他人可能会想出更快的矢量化方法:
In [10]: pd.read_clipboard()
Out[10]:
Index Return
0 2008-11-21 0.153419
1 2008-11-24 0.037421
2 2008-11-25 0.077500
In [11]: reduce(lambda x, y: (1+x)*(1+y)-1, _10['Return'])
Out[11]: 0.28931612705992227
请注意,在Python 3中,
reduce
是functools
库的一部分,尽管它是Python 2的内置函数。对于pandas
,您可以使用prod()
方法:
df.append(df.iloc[:,1:].apply(lambda col: (col + 1).prod() - 1), ignore_index=True)
# Index Return
#0 2008-11-21 0.153419
#1 2008-11-24 0.037421
#2 2008-11-25 0.077500
#3 NaN 0.289316
或者正如@Randy C所评论的,这可以进一步简化为:
df.append((df.iloc[:,1:] + 1).prod() - 1, ignore_index=True)
这是我的:
from numpy import prod
df.append(df.apply(lambda col: prod([(1+c) for c in col]) - 1), ignore_index=True)
另一个解决方案:
df.ix["Cumulative"] = (df['Return']+1).prod() - 1
这将在df['Return']
列中添加1,将所有行相乘,然后从结果中减去1。这将产生一个简单的浮点值。然后将结果放在“累积”索引中。由于该索引尚不存在,因此:
如果要跨多个列应用此选项:
df.ix['Cummulative'] = df.apply(lambda x: (x+1).prod()-1)
这将输出以下内容(我制作了第二列“Return2”,它是“Return”的副本):
有一个
cumprod()
方法用于此。这将适用于每一列
df.ix["Cumulative"] = ((df+1).cumprod()-1).iloc[-1]
这将比大型数据集上的其他解决方案快2倍左右:
In[106]: %timeit df.ix["Cumulative"] = ((df+1).cumprod()-1).iloc[-1]
10 loops, best of 3: 18.4 ms per loop
In[107]: %timeit df.ix['Cummulative'] = df.apply(lambda x: (x+1).prod()-1)
10 loops, best of 3: 32.9 ms per loop
In[110]: %timeit df.append(df.iloc[:,1:].apply(lambda col: (col + 1).prod() - 1), ignore_index=True)
10 loops, best of 3: 37.1 ms per loop
In[113]: %timeit df.append(df.apply(lambda col: prod([(1+c) for c in col]) - 1), ignore_index=True)
1 loop, best of 3: 262 ms per loop
如果你能找到一个内置的方法,我建议不要使用apply,因为apply在数据帧上循环,这会使它变慢。Bult-in方法效率很高,通常情况下,使用apply不会比Bult-in方法更快。不错的方法。只需进行计算,就可以简化为
(df['Return']+1)。prod()-1
@RandyC是的,这是解决这个问题的一种更简洁的方法。Thx@Psidom,我做了df=上述操作,效果很好,只是我的日期索引消失了,第一列下的cum Return返回一个NaN,尽管不包括任何NAN,但累积值不等于零。知道为什么吗?Thx@Jalepeno112,但如何在所有栏目中应用?更新了我的答案。没有回答你问题的那一部分。这与@Psidom的答案非常相似,但我认为这一个更具可读性。没问题。你应该看看@StevenG的答案。当然,首先将numpy作为np导入,然后:df.append(df.apply)(lambda col:prod([(1+c)表示col中的c,如果不是np.isnan(c)]-1),忽略_index=True)
。如果你尝试一下,然后让我知道如果它不工作!那真是太快了!!但我有一个专栏包括NaN。跳过这些而不返回NaN的任何解决方法?df.ix[“累计”]=((df.fillna(0)+1.cumprod()-1).iloc[-1]
将用0返回代替NaN。
df.ix["Cumulative"] = ((df+1).cumprod()-1).iloc[-1]
In[106]: %timeit df.ix["Cumulative"] = ((df+1).cumprod()-1).iloc[-1]
10 loops, best of 3: 18.4 ms per loop
In[107]: %timeit df.ix['Cummulative'] = df.apply(lambda x: (x+1).prod()-1)
10 loops, best of 3: 32.9 ms per loop
In[110]: %timeit df.append(df.iloc[:,1:].apply(lambda col: (col + 1).prod() - 1), ignore_index=True)
10 loops, best of 3: 37.1 ms per loop
In[113]: %timeit df.append(df.apply(lambda col: prod([(1+c) for c in col]) - 1), ignore_index=True)
1 loop, best of 3: 262 ms per loop