You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言:基于年份条件用lapply优化数值列批量取整的方法问询

批量处理指定年份后的数值列取整方案

问题背景

你有一个包含城市名称、年份及50+数值列的数据框,需要仅对2018年及以后的行,将所有数值列用plyr::round_any(x, 3)取整为3的倍数。现有拆分合并数据框的方法可行,但手动指定列索引效率极低,需要更简洁的批量处理方案,且不能修改年份列。

优化方案(Tidyverse 风格)

利用dplyr的across()函数可以自动批量处理目标列,无需拆分数据框,代码更简洁易维护:

library(tidyverse)
library(plyr) # 需加载plyr包提供round_any函数

# 原始数据构建(你的代码)
names <- rep(c("City A", "City B"), each = 11)
year <- rep(c(2010:2020), times = 2)
col_1 <- c(1, 17, 34, 788, 3, 4, 78, 98, 650, 45, 20,
           23, 45, 56, 877, 54, 12, 109, 167, 12, 19, 908)
col_2 <- c(3, 4, 23, 433, 2, 45, 34, 123, 98, 76, 342,
           760, 123, 145, 892, 23, 5, 90, 40, 12, 67, 98)

df <- as.data.frame(cbind(names, year, col_1, col_2)) %>%
  mutate(across(c(col_1, col_2), as.numeric))

# 核心优化代码
df <- df %>%
  mutate(
    across(
      # 自动选择所有数值列,排除year列
      .cols = where(is.numeric) & !matches("year"),
      # 仅对2018年及以后的行应用取整,其余保持原样
      .fns = ~ ifelse(year >= 2018, plyr::round_any(.x, 3), .x)
    )
  )

代码说明

  1. 列选择逻辑:where(is.numeric) & !matches("year")会自动识别所有数值类型的列,同时排除年份列,无需手动罗列50多列的名称或索引。
  2. 条件修改:通过ifelse实现行级判断,仅对符合年份条件的行修改数值,避免拆分合并数据框的繁琐操作。
  3. 灵活性扩展:如果你的数值列有统一命名前缀(比如都以col_开头),可以用starts_with("col_")替代where(is.numeric) & !matches("year"),更精准:
    df <- df %>%
      mutate(
        across(
          .cols = starts_with("col_"),
          .fns = ~ ifelse(year >= 2018, plyr::round_any(.x, 3), .x)
        )
      )
    

大数据场景备选方案(data.table)

如果数据量较大,data.table的操作效率更高:

library(data.table)
library(plyr)

setDT(df)
# 筛选出所有数值列(排除year)
num_cols <- setdiff(names(df)[sapply(df, is.numeric)], "year")
# 仅对2018年及以后的行批量修改
df[year >= 2018, (num_cols) := lapply(.SD, plyr::round_any, 3), .SDcols = num_cols]

内容的提问来源于stack exchange,提问作者evam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 09:20:35