R语言:如何基于特定id替换dataframe列a中的NA为指定文本?
问题解决:用dplyr替换指定行的NA值
需求说明
需要将数据框中id列值为3-6的行里,a列的NA替换为字符串"Transportation Element Maps 2012"。
样本数据
# 原始数据框 df = structure(list(id = c(1, 2, 3, 4, 5, 6, 7), a = c("a", "Transportation Element Maps 2012", NA, NA, NA, NA, NA)), class = "data.frame", row.names = c(NA, -7L)) # 期望得到的数据框 df1 = structure(list(id = c(1, 2, 3, 4, 5, 6, 7), a = c("a", "Transportation Element Maps 2012", "Transportation Element Maps 2012", "Transportation Element Maps 2012", "Transportation Element Maps 2012", "Transportation Element Maps 2012", NA)), class = "data.frame", row.names = c(NA, -7L))
错误写法及报错
原代码的语法完全不符合dplyr的管道和mutate规则:
# 错误写法 df1 = df %>% ifelse(id %in% 3:6) %>% mutate(a %in% NA, "Transportation Element Maps 2012")
报错信息:
Error in ifelse(., reference_number %in% 3:6) : 'list' object cannot be coerced to type 'logical'
错误原因
- 管道符
%>%的使用错误:ifelse不能直接接在管道后作为操作,管道传递的是整个数据框,而ifelse需要的是逻辑向量,不是数据框。 mutate的语法错误:mutate的正确格式是mutate(列名 = 赋值逻辑),原代码里的a %in% NA完全错误,判断NA应该用is.na(a),且不能这么写在mutate里。%in% NA本身逻辑错误:判断某个值是否为NA必须用is.na(),%in% NA会返回NA,无法正确判断。
正确实现方法
方法1:使用mutate + case_when
这是dplyr中最清晰的条件赋值方式:
library(dplyr) df1 = df %>% mutate(a = case_when( id %in% 3:6 & is.na(a) ~ "Transportation Element Maps 2012", TRUE ~ a # 其他情况保持原值不变 ))
方法2:使用mutate + ifelse
如果喜欢简洁的单条件判断,也可以用嵌套的ifelse:
df1 = df %>% mutate(a = ifelse(id %in% 3:6 & is.na(a), "Transportation Element Maps 2012", a))
方法3:使用filter + mutate(分步修改)
如果想分步操作,先筛选目标行修改,再合并回原数据:
# 筛选需要修改的行并替换 modified_rows = df %>% filter(id %in% 3:6) %>% mutate(a = "Transportation Element Maps 2012") # 合并未修改的行和修改后的行 df1 = df %>% filter(!id %in% 3:6) %>% bind_rows(modified_rows) %>% arrange(id) # 按id排序恢复原顺序
以上三种方法都能得到你期望的df1结果。
内容的提问来源于stack exchange,提问作者Ed_Gravy
相关产品推荐
相关产品推荐

