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对象,并非独立可用。
错误原因分析
- 第一个函数错误:
df$contvar中contvar作为参数,R会直接将其解析为字符串"contvar"而非传入的变量名,导致无法找到目标列。需用[[结合变量名解析来动态引用列。 - 第三个函数错误:公式
contvar ~ catvar中的变量未在函数环境中正确解析,R会在全局环境查找变量而非传入的数据框。需动态构建公式。 - 共性问题:所有函数均依赖全局环境的
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
相关产品推荐
相关产品推荐

