问题描述
我有以下数据框(为了简洁而截断的返回时间序列):
import pandas as pd
import numpy as np
df = pd.DataFrame({'return':np.array([np.nan,np.nan,0.015,-0.024,0.033,0.021,0.014,-0.092])})
我试图在第一次返回之前的最后一个 NaN 处开始索引(即“base-100”) - 同时将 100 值之前的 NaN 保持在适当的位置 - (考虑附加到现有数据框并用于绘图目的)。
我只找到了一种在返回向量中没有 NaN 时创建所述索引的方法:
df['index'] = 100*np.exp(np.nan_to_num(df['return'].cumsum()))
任何想法 - 提前谢谢!
解决方法
如果你的初始数组是
zz = np.array([np.nan,np.nan,0.015,-0.024,0.033,0.021,0.014,-0.092])
然后您可以像这样获得所需的输出(尽管可能有更优化的方法):
np.concatenate((zz[:np.argmax(np.isfinite(zz))],100*np.exp(np.cumsum(zz[np.isfinite(zz)]))))
,
使用Series.isna
,通过索引改变顺序并通过Series.idxmax
获取最后一个NaN的索引:
idx = df['return'].isna().iloc[::-1].idxmax()
传递给DataFrame.loc
,重新补缺值并使用累积和:
df['return'] = df.loc[idx:,'return'].fillna(100).cumsum()
print (df)
return
0 NaN
1 NaN
2 100.000
3 100.015
4 99.991
5 100.024
6 100.045
7 100.059
8 99.967
您可以将Series.isna
与Series.cumsum
一起使用并通过max
进行比较,然后将最后一个NaN
替换为Series.fillna
并最后使用累积总和:
s = df['return'].isna().cumsum()
df['return'] = df['return'].mask(s.eq(s.max()),df['return'].fillna(100)).cumsum()
print (df)
return
0 NaN
1 NaN
2 100.000
3 100.015
4 99.991
5 100.024
6 100.045
7 100.059
8 99.967