R语言提取dataframe最后非NA列值并替换目标列值的实现方案
R语言无硬编码替换数据框列值实现方案
核心思路
观察数据规律可知,每个name1分组下的非空name3值就是我们需要替换的目标值,无需硬编码任何字符,直接基于数据本身的分组特征实现替换即可。
最简实现(tidyverse 一步完成)
直接在生成name4列时就按规则取值,不需要后续二次替换:
library(tidyverse) df <- data.frame(name1 = c("a" , "a", "a", "a", "c", "c", "c", "c"), name2 = c(NA,"a","a",NA, NA, "c", "c", NA), name3 = c(NA, "b", "b", NA, NA, "d","d",NA)) df_result <- df %>% # 按name1分组 group_by(name1) %>% # name3非空取name3,否则取当前分组下唯一的非空name3值 mutate(name4 = ifelse(!is.na(name3), name3, unique(na.omit(name3)))) %>% ungroup()
通用映射方案(适配更复杂的替换逻辑)
如果后续替换逻辑更灵活,可以先提取映射关系再替换,全程无硬编码:
# 1. 提取name1到目标值的映射关系 mapping <- df %>% filter(!is.na(name3)) %>% distinct(name1, target_val = name3) # 2. 生成name4后按映射替换 df_result <- df %>% mutate(name4 = ifelse(!is.na(name3), name3, name1)) %>% left_join(mapping, by = "name1") %>% mutate(name4 = ifelse(name4 == name1, target_val, name4)) %>% select(-target_val)
base R 实现方案
不需要加载第三方包的实现方式:
# 生成映射向量 mapping <- unique(na.omit(df[, c("name1", "name3")])) map_vec <- setNames(mapping$name3, mapping$name1) # 生成并替换name4 df$name4 <- ifelse(!is.na(df$name3), df$name3, df$name1) df$name4 <- ifelse(df$name4 %in% names(map_vec), map_vec[df$name4], df$name4)
以上所有方案输出的结果都和提供的期望输出一致,且全程没有硬编码a/b/c/d等字符,数据分组变化后不需要修改代码逻辑即可复用。
内容的提问来源于stack exchange,提问作者Anh
相关产品推荐
相关产品推荐

