如何在Pandas DataFrame中按投资分组计算IRR?
按投资项目分组计算IRR的解决方案
问题原因
你遇到的「不可哈希的DataFrame」错误,是因为在groupby后直接将整个子DataFrame传递给IRR计算函数,而IRR工具(比如PYXIRR)需要的是日期序列和现金流序列,而非整个DataFrame对象。
前提准备
首先确保你的DataFrame中日期列是datetime类型,否则无法正确计算时间加权的IRR:
import pandas as pd # 示例数据 df = pd.DataFrame({ "Investments": ["Investment A", "Investment A", "Investment A", "Investment B", "Investment B", "Investment C", "Investment C", "Investment C", "Investment C"], "Date": ["1/1/2000", "12/31/2020", "12/31/2021", "5/31/2005", "12/31/2021", "3/6/2010", "12/31/2011", "12/31/2012", "12/31/2021"], "Cash Flow": [-100, 100, 100, -500, 600, -100, -100, -50, 300] }) # 转换日期列为datetime类型 df["Date"] = pd.to_datetime(df["Date"])
方案一:使用PYXIRR(推荐,支持非定期现金流)
PYXIRR支持基于实际日期的IRR计算,适合现金流时间间隔不规则的场景。正确的分组计算方式是从每个子分组中提取排序后的日期和现金流序列:
from pyxirr import irr def calc_irr(group): # 必须按日期排序,确保现金流时间顺序正确 sorted_group = group.sort_values("Date") return irr(sorted_group["Date"], sorted_group["Cash Flow"]) # 分组计算并格式化结果 irr_result = df.groupby("Investments").apply(calc_irr).reset_index(name="IRR") irr_result["IRR"] = irr_result["IRR"].apply(lambda x: f"{x*100:.0f}%")
运行后得到的结果与你的目标输出一致:
| Investments | IRR |
|---|---|
| Investment A | 50% |
| Investment B | 6% |
| Investment C | 10% |
方案二:使用numpy.irr(适合定期现金流)
如果你的现金流是严格定期(比如每年固定日期),可以用numpy.irr,它不考虑实际日期间隔,仅按现金流的顺序计算:
import numpy as np def calc_irr_numpy(group): sorted_group = group.sort_values("Date") return np.irr(sorted_group["Cash Flow"]) irr_result_numpy = df.groupby("Investments").apply(calc_irr_numpy).reset_index(name="IRR") irr_result_numpy["IRR"] = irr_result_numpy["IRR"].apply(lambda x: f"{x*100:.0f}%")
注意:如果现金流时间间隔不规则,此方法结果会有偏差,优先选择PYXIRR。
关键注意点
- 所有分组计算前必须按日期排序,否则现金流顺序错误会导致IRR结果完全失真
- 确保现金流的符号正确:初始投资为负,后续回款为正
内容的提问来源于stack exchange,提问作者afkkek
相关产品推荐
相关产品推荐

