使用groupby计算收益率返回全NaN值的问题求助
问题排查:计算资产类型收益率全为NaN的原因及解决方法
问题背景
现有如下结构的DataFrame:
city Year Asset_Type TotalTransac NbBiens psqm_city 0 Agadir 2010.0 Appart 3225 3156 6276.923077 1 Agadir 2010.0 Maison_Dar 37 37 8571.428571 2 Agadir 2010.0 Villa 107 103 6279.469027 3 Agadir 2011.0 Appart 2931 2816 6516.853933 4 Agadir 2011.0 Maison_Dar 33 32 9000.000000 .. ... ... ... ... ... ... 171 Tanger 2019.0 Maison_Dar 268 263 12158.385093 172 Tanger 2020.0 Appart 5223 5180 5760.869565 173 Tanger 2020.0 Maison_Dar 193 192 13500.000000
尝试用以下代码按Asset_Type计算收益率:
Index_byCity["Returns"] = Index_byCity.groupby(['city','Year','Asset_Type'])['psqm_city'].apply(lambda x: (x - x.shift(1))-1 )
结果所有Returns值都是NaN:
0 NaN 1 NaN 2 NaN 3 NaN 4 NaN .. 171 NaN 172 NaN 173 NaN 174 NaN 175 NaN Name: Returns, Length: 176, dtype: float64
原因分析
- 分组逻辑错误:你在
groupby里包含了Year,这意味着每个分组是(city, Year, Asset_Type)的组合,而从DataFrame可以看到,每个这样的组合只有1行数据。对单个元素的序列调用x.shift(1),结果必然是NaN,因为没有前一个元素可以偏移。 - 收益率公式错误:正确的收益率计算应该是
(当前值/前一期值) - 1,而不是(当前值-前一期值)-1,后者的计算逻辑完全不符合收益率的定义。
解决方法
步骤1:修正分组逻辑
要计算同一城市、同一资产类型在不同年份的收益率,groupby应该只按city和Asset_Type分组,这样每个分组内会包含该城市该资产类型的所有年份数据,才能进行偏移计算。
步骤2:修正收益率公式
使用正确的收益率计算公式(x / x.shift(1)) - 1。
最终代码
# 按城市和资产类型分组,计算收益率 Index_byCity["Returns"] = Index_byCity.groupby(['city', 'Asset_Type'])['psqm_city'].apply(lambda x: (x / x.shift(1)) - 1)
补充说明
- 每个分组的第一行(最早年份)会因为没有前一期数据而保持NaN,这是正常现象。
- 如果需要保留原始数据的顺序,确保DataFrame已经按
city、Asset_Type和Year排序,否则偏移会出错。可以先执行排序:
Index_byCity = Index_byCity.sort_values(['city', 'Asset_Type', 'Year'])
内容的提问来源于stack exchange,提问作者bravopapa
相关产品推荐
相关产品推荐

