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

如何对训练集除指定列外的列标准化,并同步缩放测试集?

嘿,我太懂你这种手动折腾缩放的痛苦了——一会儿要找列索引,一会儿要存均值标准差,稍不注意就把测试集的统计量混进去了,完全是重复劳动!下面给你几个更优雅的解决方案,从基础R到专门的机器学习工具都有,挑你顺手的来:

方法一:基础R封装函数,复用性拉满

如果你习惯用基础R,可以把整个流程封装成一个函数,一次写好之后随时调用,再也不用重复敲代码:

# 定义通用缩放函数
scale_selected <- function(train_data, test_data, exclude_cols) {
  # 筛选出需要缩放的列(排除指定列)
  scale_cols <- setdiff(names(train_data), exclude_cols)
  
  # 计算训练集目标列的均值和标准差(自动忽略NA)
  train_means <- colMeans(train_data[scale_cols], na.rm = TRUE)
  train_sds <- apply(train_data[scale_cols], 2, sd, na.rm = TRUE)
  
  # 缩放训练集
  train_scaled <- train_data
  train_scaled[scale_cols] <- scale(train_data[scale_cols], center = train_means, scale = train_sds)
  
  # 用训练集的统计量缩放测试集
  test_scaled <- test_data
  test_scaled[scale_cols] <- lapply(scale_cols, function(col) {
    (test_data[[col]] - train_means[col]) / train_sds[col]
  }) %>% as.data.frame()
  
  # 返回缩放后的数据集+统计量(方便后续检查)
  list(
    train_scaled = train_scaled,
    test_scaled = test_scaled,
    scaling_stats = list(means = train_means, sds = train_sds)
  )
}

# 示例用法
set.seed(123)
train_df <- data.frame(
  id = 1:10,
  category = sample(c("A", "B"), 10, replace = TRUE),
  num1 = rnorm(10, 50, 10),
  num2 = rnorm(10, 20, 5),
  num3 = rnorm(10, 100, 20)
)

test_df <- data.frame(
  id = 11:15,
  category = sample(c("A", "B"), 5, replace = TRUE),
  num1 = rnorm(5, 50, 10),
  num2 = rnorm(5, 20, 5),
  num3 = rnorm(5, 100, 20)
)

# 调用函数,排除id和category列
result <- scale_selected(train_df, test_df, exclude_cols = c("id", "category"))

# 查看结果
result$train_scaled
result$test_scaled

方法二:tidyverse管道风格,代码更整洁

如果你平时用dplyr这类工具,用管道流处理会更符合你的代码习惯,可读性也更强:

library(dplyr)

# 先从训练集提取缩放所需的均值和标准差
exclude_cols <- c("id", "category")
scaling_stats <- train_df %>%
  select(-all_of(exclude_cols)) %>%
  summarize(across(everything(), list(mean = mean, sd = sd), na.rm = TRUE))

# 缩放训练集
train_scaled <- train_df %>%
  mutate(across(-all_of(exclude_cols), ~ (.x - scaling_stats[[paste0(cur_column(), "_mean")]]) / scaling_stats[[paste0(cur_column(), "_sd")]]))

# 复用训练集的统计量缩放测试集
test_scaled <- test_df %>%
  mutate(across(-all_of(exclude_cols), ~ (.x - scaling_stats[[paste0(cur_column(), "_mean")]]) / scaling_stats[[paste0(cur_column(), "_sd")]]))

方法三:用caret一键搞定,机器学习场景首选

如果你的场景是机器学习预处理,caret包的preProcess绝对是最优解——它会自动帮你存储训练集的统计量,直接用predict就能处理测试集,完全不用手动管理均值和标准差:

library(caret)

exclude_cols <- c("id", "category")
# 基于训练集的目标列创建预处理对象(center=中心化,scale=标准化)
pre_proc <- preProcess(train_df %>% select(-all_of(exclude_cols)), method = c("center", "scale"))

# 一键缩放训练集和测试集
train_scaled <- predict(pre_proc, train_df)
test_scaled <- predict(pre_proc, test_df)

几个小提醒:

  • 如果数据里有NA,记得在计算均值/标准差时加上na.rm = TRUE,避免出错;
  • 分类变量、ID列这类确实不需要缩放,排除它们是正确的操作;
  • caret的preProcess还支持很多其他预处理方法(比如归一化、PCA、缺失值填充),如果后续有其他需求可以直接扩展。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 04:21:21