R语言:用另一数据框批量替换主数据框缺失值的问题
问题:按SKU匹配填充主数据框COST列的NA值
数据模拟
主数据框(MAIN DF)
index=c(1:10) SKU = c('I-1','I-9','I-4','I-1','I-6','I-9','I-2','I-3','I-8','I-9') COST=c(17,15,10,NA,12,NA,8,12,10,NA) main = data.frame(index, SKU, COST) main
填充数据框(FILL DF)
SKU = c('I-1','I-2','I-3','I-4','I-6','I-8','I-9') COST=c(19,8,12,10,12,10,11) fill = data.frame(SKU, COST) fill
需求说明
需根据fill数据框中SKU对应的唯一成本值(由聚合均值计算得到),填充main数据框COST列的NA值。实际业务场景中,SKU会因促销存在多个成本记录,fill是每个SKU的标准化成本。
原代码问题
尝试以下代码后,无法填充所有NA值:
main$COST[is.na(main$COST)] <- fill$COST[match(main$SKU, fill$SKU)] main
预期索引4、6、10的NA会被fill中对应值(19、11、11)填充,但实际索引6仍为NA,原代码仅能处理单个NA,无法应对同一SKU的多个NA情况。
问题原因
原代码的赋值逻辑存在长度不匹配问题:
fill$COST[match(main$SKU, fill$SKU)]生成的是与main行数一致的10元素向量,包含所有SKU的填充值- 但赋值时仅选中
main$COST中的3个NA位置,R会自动截取向量的前3个值来匹配赋值,而这前3个值中没有对应索引6、10的SKU-I9的填充值,导致部分NA未被正确替换。
解决方法
方法1:修正base R赋值逻辑
先生成完整的填充值向量,再精准替换NA位置:
# 生成每个SKU对应的填充值向量 fill_values <- fill$COST[match(main$SKU, fill$SKU)] # 仅替换COST为NA的位置 main$COST[is.na(main$COST)] <- fill_values[is.na(main$COST)]
方法2:使用dplyr关联填充(推荐,可读性高)
通过left_join关联数据框,再合并COST列:
library(dplyr) main <- main %>% left_join(fill, by = "SKU", suffix = c("", "_fill")) %>% mutate(COST = ifelse(is.na(COST), COST_fill, COST)) %>% select(-COST_fill)
方法3:base R merge方式
# 合并两个数据框,保留main的所有行 merged <- merge(main, fill, by = "SKU", suffixes = c("", "_fill"), all.x = TRUE) # 填充NA值 merged$COST <- ifelse(is.na(merged$COST), merged$COST_fill, merged$COST) # 还原原数据框结构并按index排序 main <- merged[, c("index", "SKU", "COST")] main <- main[order(main$index), ]
内容的提问来源于stack exchange,提问作者Joe Mcsweeney
相关产品推荐
相关产品推荐

