predict函数无法预测NA值?lowess填充NA遇行数不匹配报错
1. 为何predict函数无法对NA值进行预测?
其实大部分predict函数的逻辑是基于模型训练时的输入规则来的——训练模型的时候,你肯定是用没有缺失值的完整特征数据来拟合的对吧?模型根本没学过怎么处理NA值,它不知道NA代表什么,自然没法生成合理的预测结果。
举个简单例子:你用线性回归模型拟合了y~x,训练时x都是完整数值,当你predict的时候输入x=NA,模型根本不知道这个NA对应的y应该是多少,直接就会报错。而且很多模型在训练阶段就会自动剔除含NA的样本,所以预测阶段遇到NA,相当于给模型喂了它从未见过的“无效输入”,肯定没法处理。
2. 解决lowess平滑填充NA时的报错问题
这个报错其实很直观:Error in $<-.data.frame(*tmp*, sr.smooth, value = c(...)): replacement has 50 rows, data has 128——你要赋值给sr.smooth的平滑结果只有50行,但你的原数据框modis.raw2有128行,行数对不上,R当然会拒绝这个操作。
为啥会出现这种情况?因为你直接用lowess(modis.raw2$day, modis.raw2$sr.og)的时候,lowess会自动忽略掉sr.og里有NA的行,只对剩下的50个非NA数据点计算平滑值,返回的结果自然只有50个值。而你要把它放到128行的数据框里,肯定会不匹配。
给你两个实用的解决办法:
- 方法一:用基础R的
approx插值补全所有时间点
这个方法最直接,先让lowess处理非NA数据,再把平滑结果插值到所有日期上:
# 第一步:找出sr.og没有NA的行索引 non_na_rows <- !is.na(modis.raw2$sr.og) # 第二步:用非NA数据运行lowess lowess_result <- lowess(modis.raw2$day[non_na_rows], modis.raw2$sr.og[non_na_rows]) # 第三步:用插值把平滑值扩展到所有日期(包括原来有NA的日期) modis.raw2$sr.smooth <- approx(lowess_result$x, lowess_result$y, xout = modis.raw2$day)$y
approx会根据lowess拟合出来的平滑曲线,给每个day对应的位置生成一个平滑值,这样得到的sr.smooth就和原数据框一样是128行,赋值就不会报错了。
- 方法二:用专门的缺失值填充工具(可选)
如果不想自己写插值逻辑,也可以用zoo包的na.approx结合lowess,或者forecast包的na.interp函数,这些工具会自动帮你处理缺失值的填充逻辑,比如:
library(zoo) # 先对sr.og做lowess平滑,再用插值填充NA modis.raw2$sr.smooth <- na.approx(lowess(modis.raw2$day, modis.raw2$sr.og)$y, x = modis.raw2$day)
不过这个需要先安装对应的包,如果想用基础R搞定,方法一就完全够用了。
内容的提问来源于stack exchange,提问作者Ana

