如何基于含列名与值的另一DataFrame替换目标DataFrame的值?
如何根据修正DataFrame批量更新目标DataFrame的指定值?
首先定义目标成绩DataFrame和修正信息DataFrame:
library(dplyr) # 目标成绩表 id <- c(1 , 2) name <- c('John', 'Ninaa') score1 <- c(8, 6) score2 <- c(NA, 7) df <- data.frame(id, name, score1, score2) # 修正信息表 id <- c(2,1) column <- c('name', 'score2') new_value <- c('Nina', 9) corrections <- data.frame(id, column, new_value)
需求是:根据修正表中的id和column字段,定位目标表中的对应位置,将值替换为new_value。
你之前的尝试无法生效,原因是mutate中不能直接用动态列名作为赋值目标,且replace函数无法同时处理多列、多行的分散修正需求。以下是几种可行的实现方法:
方法1:循环遍历修正行(直观易懂)
适合修正条目较少的场景,直接遍历修正表的每一行,定位目标表的对应位置完成替换:
df_corrected <- df for (i in 1:nrow(corrections)) { corr_row <- corrections[i, ] # 匹配id并定位指定列,替换值 df_corrected[df_corrected$id == corr_row$id, corr_row$column] <- corr_row$new_value }
方法2:dplyr管道式实现(函数式风格)
利用dplyr的rowwise和across函数,动态匹配每个行和列的修正规则:
library(dplyr) df_corrected <- df %>% rowwise() %>% mutate( # 遍历所有需要修正的列 across(all_of(corrections$column), ~ { # 筛选当前行id和当前列对应的修正值 corr <- corrections %>% filter(id == !!cur_data()$id, column == cur_column()) # 有修正值则替换,否则保留原值 if (nrow(corr) > 0) corr$new_value else .x }) ) %>% ungroup()
方法3:转宽修正表后合并替换(适合批量修正)
先将长格式的修正表转为宽格式,再通过left_join合并后完成替换,适合需要修正的列较多的场景:
library(dplyr) library(tidyr) # 将修正表转为宽格式:id为键,列名为列,修正值为内容 corrections_wide <- corrections %>% pivot_wider(names_from = column, values_from = new_value, names_prefix = "corr_") # 合并后替换对应列 df_corrected <- df %>% left_join(corrections_wide, by = "id") %>% mutate( name = ifelse(!is.na(corr_name), corr_name, name), score2 = ifelse(!is.na(corr_score2), corr_score2, score2) ) %>% # 移除临时修正列 select(-starts_with("corr_"))
执行任意一种方法后,df_corrected即为修正后的结果:
> df_corrected id name score1 score2 1 1 John 8 9 2 2 Nina 6 7
内容的提问来源于stack exchange,提问作者Nina van Bruggen
相关产品推荐
相关产品推荐

