如何在R语言中基于最近邻点为含NA值的点赋值?
用最近邻非NA值填充数据集中的缺失值
原始数据集
我有一个包含X、Y坐标和value列的数据集,结构如下:
df <- data.frame(ID=c(1,2,3,4,5,6,7), X=c(420729, 420329, 518020, 518013, 517620, 517604, 518024), Y=c(32072, 32032, 41802, 41801, 41762, 41760, 41802), value=c(123, 42, NA, 22, NA, 55, 43))
需求
我想要给value列中含NA值的点,赋予其最近邻非NA点的value值。
当前操作遇到的问题
我尝试用RANN包的nn2函数找最近邻,但操作时需要删除value列:
df1 <- subset(df, select=-c(value)) # 修正原代码拼写错误 closest <- nn2(data=df1, k=2)[[1]]
得到的最近邻索引如下:
[,1] [,2] [1,] 1 2 [2,] 2 1 [3,] 3 7 [4,] 4 3 [5,] 5 6 [6,] 6 5 [7,] 7 3
现在我有两个问题:
- 不知道如何把最近邻的value值赋值给NA的点
- 如果最近邻本身也是NA,能不能直接查找距离最近的非NA点来填充
期望的最终数据集
最终想要得到如下结果:
df3 <- data.frame(ID=c(1,2,3,4,5,6,7), X=c(420729, 420329, 518020, 518013, 517620, 517604, 518024), Y=c(32072, 32032, 41802, 41801, 41762, 41760, 41802), value=c(123, 42, 43, 22, 55, 55, 43))
解决方案
方法1:直接基于非NA点查找最近邻(推荐)
这种方法直接以所有非NA点为参考集,确保找到的最近邻一定是有值的点,无需后续判断:
library(RANN) # 拆分有值和缺失值的子集 has_value <- df[!is.na(df$value), ] missing_value <- df[is.na(df$value), ] # 为缺失值点匹配最近的非NA点 nn_result <- nn2(data = has_value[, c("X", "Y")], query = missing_value[, c("X", "Y")], k = 1) # 填充缺失值 missing_value$value <- has_value$value[nn_result$nn.idx[, 1]] # 合并并按ID排序得到最终结果 df_filled <- rbind(has_value, missing_value) df_filled <- df_filled[order(df_filled$ID), ] print(df_filled)
方法2:基于已有的最近邻索引处理
如果已经计算了全量最近邻,可以循环检查邻居是否为NA,直到找到第一个非NA值:
library(RANN) # 重新计算正确的最近邻索引 closest <- nn2(data=subset(df, select=-c(value)), k=2)[[1]] # 遍历填充缺失值 for(i in 1:nrow(df)){ if(is.na(df$value[i])){ # 从第2个邻居开始查找(第1个是自身) neighbor_idx <- closest[i, 2] # 如果当前邻居是NA,继续查找该邻居的最近邻 while(is.na(df$value[neighbor_idx])){ # 若存在连续NA,建议增大nn2的k值获取更多邻居选项 neighbor_idx <- closest[neighbor_idx, 2] } df$value[i] <- df$value[neighbor_idx] } } print(df)
说明
- 方法1更高效,直接规避了邻居为NA的问题,适合大部分场景
- 方法2适合已计算好全量最近邻的情况,但需注意连续NA的场景要增大
nn2的k参数,避免循环问题
内容的提问来源于stack exchange,提问作者Star Cha
相关产品推荐
相关产品推荐

