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

R语言计算数据框统计量时列名不符合预期问题排查

问题:计算数据框数值列均值和标准差时列名自动添加前缀

我用R代码计算class数据框数值列的均值和标准差,预期新列名为Age_mean、Age_std,但实际输出列名变成了Age.Age_mean、Age.Age_std,不清楚为什么会额外添加Age.前缀。

数据与代码

class <- structure(list(Name = c("Alfred", "Alice", "Barbara", "Carol", 
"Henry", "James", "Jane", "Janet", "Jeffrey", "John", "Joyce", 
"Judy", "Louise", "Mary", "Philip", "Robert", "Ronald", "Thomas", 
"William"), Sex = c("M", "F", "F", "F", "M", "M", "F", "F", "M", 
"M", "F", "F", "F", "F", "M", "M", "M", "M", "M"), Age = c(14, 
13, 13, 14, 14, 12, 12, 15, 13, 12, 11, 14, 12, 15, 16, 12, 15, 
11, 15), Height = c(69, 56.5, 65.3, 62.8, 63.5, 57.3, 59.8, 62.5, 
62.5, 59, 51.3, 64.3, 56.3, 66.5, 72, 64.8, 67, 57.5, 66.5), 
    Weight = c(112.5, 84, 98, 102.5, 102.5, 83, 84.5, 112.5, 
    84, 99.5, 50.5, 90, 77, 112, 150, 128, 133, 85, 112)), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -19L))


out1 <- list()

calc_mean <- function(data, vars, out) {
 
  vars <- syms(vars)
  print(vars)
  for (v in vars){
    print(v)
  out1[[v]] <- data %>% summarise('{{v}}_mean' := mean(!! v), '{{v}}_std' := sd(!! v))
  out2 <-  data.frame(out1)
  assign(out, out2, envir =.GlobalEnv)
  }

  return(out2)
}

calc_mean(data=class, vars=c('Age','Height'), out='want')

实际输出

Age.Age_mean Age.Age_std Height.Height_mean Height.Height_std
1     13.31579    1.492672           62.33684          5.127075

原因分析

问题出在列表转数据框的命名规则:你将每个变量的统计结果存入列表out1时,用符号对象v(即Age、Height)作为列表元素名;当执行data.frame(out1)将列表转换为数据框时,R会自动用「列表元素名 + 点 + 原列名」的格式重命名列,以此区分不同列表元素中的列,最终就出现了Age.Age_mean这类带前缀的列名。

解决方案

方案1:修正原有循环逻辑

放弃用列表存储后转数据框的方式,改为逐个合并临时数据框,避免自动命名:

calc_mean <- function(data, vars, out) {
  vars <- syms(vars)
  # 初始化空的 tibble
  out2 <- tibble()
  for (v in vars){
    # 生成当前变量的统计结果
    temp <- data %>% summarise('{{v}}_mean' := mean(!!v), '{{v}}_std' := sd(!!v))
    # 合并到结果数据框
    out2 <- bind_cols(out2, temp)
  }
  assign(out, out2, envir = .GlobalEnv)
  return(out2)
}

方案2:用across简化代码(推荐)

使用tidyverse的across函数,无需循环即可批量处理所有目标变量,直接生成符合预期的列名:

calc_mean <- function(data, vars, out) {
  out2 <- data %>%
    summarise(
      across(
        all_of(vars), 
        list(mean = mean, std = sd), 
        .names = "{.col}_{.fn}"  # 自定义列名格式:变量名_统计量
      )
    )
  assign(out, out2, envir = .GlobalEnv)
  return(out2)
}

运行修正后的函数,want数据框的列名将变为Age_mean、Age_std、Height_mean、Height_std,完全符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:31:04