R dataframe指定列区间内大于等于10的值替换为0的实现方法
你的代码存在两个核心问题:
- 替换逻辑写反:你写的
~1 * (. >= 10)会把≥10的值转为1、<10的值转为0,和你要的「≥10替换为0、其余保留原值」的需求完全不符。 - 列筛选规则不对:
mutate_if(is.numeric)会匹配所有数值列,如果你后续数据集新增其他数值列也会被误修改,不符合你仅修改S_2018_p到S_2021_p这几列的要求。
以下是两种常用的可直接运行的实现方案:
方案1:data.table原生实现(推荐,针对data.table格式性能最优)
library(data.table) # 先指定需要修改的列,两种方式选一种即可 # 方式A:精准指定年份范围,不会匹配到其他同名格式的列 cols <- paste0("S_", 2018:2021, "_p") # 方式B:正则匹配所有S_xxxx_p格式的列,适合年份多的场景 # cols <- grep("^S_\\d{4}_p$", names(df1), value = TRUE) # 不修改原表的话先复制一份,需要直接修改原表可以跳过copy步骤 df2 <- copy(df1) df2[, (cols) := lapply(.SD, function(x) fifelse(x >= 10, 0, x)), .SDcols = cols]
这里用data.table自带的fifelse比基础ifelse性能更好,大数据量下优势明显。
方案2:dplyr风格实现(适合习惯tidyverse语法的场景)
library(dplyr) df2 <- df1 %>% # 匹配符合命名规则的列执行修改 mutate(across(starts_with("S_") & ends_with("_p"), ~ifelse(.x >= 10, 0, .x)))
如果使用低于1.0.0版本的旧版dplyr,可使用兼容写法:
df2 <- df1 %>% mutate_at(vars(starts_with("S_"), ends_with("_p")), ~ifelse(. >= 10, 0, .))
内容的提问来源于stack exchange,提问作者fjurt
相关产品推荐
相关产品推荐

