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

R语言自定义统计函数报错排查:对象未找到与数值类型问题

R语言统计检验函数封装问题及解决

数据背景

data <- iris
# 重命名列
names(data)[names(data) == "Sepal.Length"] <- "count"

待封装的原始统计检验逻辑

  • Shapiro正态性检验:
shapiro <- shapiro.test(data$count)
  • 条件执行Bartlett方差齐性检验:
if(shapiro$p.value > 0.05) {
  require(tidyverse)
  bart <- bartlett.test(count ~ species, data=data)
} 
  • 条件选择方差分析方法:
if ((shapiro$p.value > 0.05) && exists("bart")){
  if(bart$p.value > 0.05) { 
    OneWay <- aov(count ~ species, data = data) 
    oneway <- summary(OneWay) #正态分布且方差齐性
  } else  {
    welch <- oneway.test(count ~ species, data = data) #Welch方差分析,正态分布、方差不齐
  }
} else {
  fligner <- fligner.test(count ~ species, data = data)
   #非正态分布时执行Fligner-Killeen方差齐性检验
} 

函数编写中的错误

第一个函数错误

编写的Shapiro检验函数:

perform_shapiro <- function(df, contvar) {
   shapiro.test(df$contvar)
}
perform_shapiro(df = data, contvar = count)

报错:Error in shapiro.test(df$contvar) : is.numeric(x) is not TRUE.

第三个函数错误

编写的方差分析选择函数:

perform_oneway_welch_fligner <- function(df, contvar, catvar){
      if ((shapiro$p.value > 0.05) && exists("bart")){
      if(bart$p.value > 0.05) { 
        OneWay <- aov(contvar ~ catvar, data = df) 
        oneway <- summary(OneWay) #正态分布且方差齐性
        print(oneway)
      } else  {
        welch <- oneway.test(contvar ~ catvar, data = df) #Welch方差分析,正态分布、方差不齐
        print(welch)
      }
    } else {
      fligner <- fligner.test(contvar ~ catvar, data = df)
       #非正态分布时执行Fligner-Killeen方差齐性检验
      print(fligner)
    } 
}
perform_oneway_welch_fligner(data, count, species)

报错:Error in eval(predvars, data, env) : object 'count' not found.

注:第二个函数看似运行正常,但实际依赖全局环境的shapiro对象,并非独立可用。

错误原因分析

  1. 第一个函数错误:df$contvar中contvar作为参数,R会直接将其解析为字符串"contvar"而非传入的变量名,导致无法找到目标列。需用[[结合变量名解析来动态引用列。
  2. 第三个函数错误:公式contvar ~ catvar中的变量未在函数环境中正确解析,R会在全局环境查找变量而非传入的数据框。需动态构建公式。
  3. 共性问题:所有函数均依赖全局环境的shapiro、bart对象,函数独立性缺失,无法单独运行。

修正后的完整函数

整合所有检验逻辑为独立函数,解决变量解析与依赖问题:

perform_stats_tests <- function(df, contvar, catvar) {
  # 解析传入的变量名为字符串
  cont_str <- deparse(substitute(contvar))
  cat_str <- deparse(substitute(catvar))
  
  # 1. Shapiro正态性检验
  shapiro_res <- shapiro.test(df[[cont_str]])
  cat("Shapiro-Wilk正态性检验结果:\n")
  print(shapiro_res)
  
  # 2. 条件执行Bartlett检验
  bart_res <- NULL
  if (shapiro_res$p.value > 0.05) {
    # 动态构建检验公式
    bart_formula <- reformulate(cat_str, response = cont_str)
    bart_res <- bartlett.test(bart_formula, data = df)
    cat("\nBartlett方差齐性检验结果:\n")
    print(bart_res)
  }
  
  # 3. 条件选择统计方法
  cat("\n最终检验结果:\n")
  if (!is.null(bart_res)) {
    if (bart_res$p.value > 0.05) {
      # 正态且方差齐,执行单因素ANOVA
      aov_formula <- reformulate(cat_str, response = cont_str)
      aov_res <- aov(aov_formula, data = df)
      print(summary(aov_res))
    } else {
      # 正态但方差不齐,执行Welch方差分析
      welch_formula <- reformulate(cat_str, response = cont_str)
      welch_res <- oneway.test(welch_formula, data = df)
      print(welch_res)
    }
  } else {
    # 非正态分布,执行Fligner-Killeen检验
    fligner_formula <- reformulate(cat_str, response = cont_str)
    fligner_res <- fligner.test(fligner_formula, data = df)
    print(fligner_res)
  }
  
  # 返回所有检验结果(可选,便于后续处理)
  list(
    shapiro = shapiro_res,
    bartlett = bart_res,
    final_test = if (!is.null(bart_res)) {
      if (bart_res$p.value > 0.05) summary(aov_res) else welch_res
    } else fligner_res
  )
}

使用示例

# 调用函数
results <- perform_stats_tests(data, count, species)

由于data$count的Shapiro检验p值<0.05,函数会直接输出Fligner-Killeen检验结果,符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 00:50:29