我的问题不是围绕如何计算内部收益率(emr),而是在给定类似于下面的数据集的情况下,如何在不等待的情况下最好地计算内部收益率(emr)样本量急剧增加的结果需要几个月的时间。
我正在使用np.irr
function
import pandas as pd
import numpy as np
date_list =['2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04','2018-01-05', '2018-01-06', '2018-01-07', '2018-01-14','2018-01-21', '2018-01-31','2018-02-08', '2018-02-28']
ids_list = [1,1,1,1,2,2,2,2,3,3,3,3]
flows_list = [ -10, 2, 2, 10, -50, 25, 20, 20, -100, 0, 3, 150]
df = pd.DataFrame(list(zip(date_list,ids_list,flows_list)), columns=['Date','ID','Flow'])
df['Date'] = pd.to_datetime(df['Date'],format='%Y-%m-%d')
产生下面的数据集
In [144]: df
Out[144]:
Date ID Flow
0 2018-01-01 1 -10
1 2018-01-02 1 2
2 2018-01-03 1 2
3 2018-01-04 1 10
4 2018-01-05 2 -50
5 2018-01-06 2 25
6 2018-01-07 2 20
7 2018-01-14 2 20
8 2018-01-21 3 -100
9 2018-01-31 3 0
10 2018-02-08 3 3
11 2018-02-28 3 150
数据说明
Date
是现金流入或流出的日子。
ID
本质上是每笔投资的唯一ID。
Flow
是该ID
(投资)的现金流量。
我需要使用每日频率作为np.irr
如果我做一个简单的pandas.groupby
In [145]: df.groupby(['ID'])['Flow'].agg(np.irr)
Out[145]:
ID
1 0.141962
2 0.150155
3 0.153450
Name: Flow, dtype: float64
因此,对于ID
1,由于我的频率是一致的,因此返回的np.irr
很有意义。
不过,对于其余的日期,您会发现日期之间的间隔不是相等的。
“手动”为ID 3计算np.irr
的示例
df.loc[df.ID ==3]['Date'].apply(lambda x: (x - min(df.loc[df.ID ==3]['Date'])).days)
8 0
9 10
10 18
11 38
Name: Date, dtype: int64
上面可以看到,每个现金流都发生在开始,第10、18和最后的第38天。
cfs = np.zeros(39)
cfs[[0,10,18,38]] = df.loc[df.ID ==3]['Flow'].values
np.irr(cfs)
这会为np.irr
3产生实际 ID
:
Out[155]: 0.011386397119650837
如何以{strong>最优方式在现金流频率不一致的
np.irr
上计算pandas.DataFrame
?
答案 0 :(得分:0)
这似乎是我能找到的最最佳方法。避免循环!
加载示例数据
import pandas as pd
import numpy as np
date_list =['2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04','2018-01-05', '2018-01-06', '2018-01-07', '2018-01-14','2018-01-21', '2018-01-31','2018-02-08', '2018-02-28']
ids_list = [1,1,1,1,2,2,2,2,3,3,3,3]
flows_list = [ -10, 2, 2, 10, -50, 25, 20, 20, -100, 0, 3, 150]
df = pd.DataFrame(list(zip(date_list,ids_list,flows_list)), columns=['Date','ID','Flow'])
df['Date'] = pd.to_datetime(df['Date'],format='%Y-%m-%d')
重新索引数据框以包含0的现金流
def reindex_by_date_and_fill(df,groupby_column='ID',value_column='Flow'):
dates = pd.date_range(df.index.min(), df.index.max())
return pd.concat([df.reindex(dates)[groupby_column].ffill(),df.reindex(dates,fill_value=0)[value_column]],axis=1)
df_test = df.set_index(['Date']).groupby(['ID'],as_index=False).apply(reindex_by_date_and_fill).reset_index(0,drop=True)
我从以下两个帖子中得到了这个主意:
Add missing dates to pandas dataframe
Pandas reindex dates in Groupby
基本上,它填写缺少的天并将现金流量填充为零。这样一来,您可以每天获得每笔投资的频率,同时又保持现金流量的还款期。
In [54]: df_test.head(10)
Out[54]:
ID Flow
2018-01-01 1.0 -10
2018-01-02 1.0 2
2018-01-03 1.0 2
2018-01-04 1.0 10
2018-01-05 2.0 -50
2018-01-06 2.0 25
2018-01-07 2.0 20
2018-01-08 2.0 0
2018-01-09 2.0 0
2018-01-10 2.0 0
这样您就可以使用
groupby
In [60]: df_test.groupby(['ID'])['Flow'].agg(np.irr)
Out[60]:
ID
1.0 0.141962
2.0 0.082212
3.0 0.011386
Name: Flow, dtype: float64