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

如何用sapply传入双参数实现多变量分组加权两样本t检验?

多变量分组加权两样本t检验实现方案

问题描述

原代码可实现按carb分组对disp变量执行加权两样本t检验(以am为分组依据),但扩展到多变量(如cyl、drat、disp)时出现报错Error in var(x) : 'x' is NULL,需解决如何同时传入分组数据集与变量列表,并输出结构化结果表格的问题。

原可运行代码

library(tidyverse)
library(weights)
df_list <- split(mtcars, mtcars$carb)
multiple_wt_ttest <- function(df) {
  ttest = wtd.t.test(x=subset(df, am == 0)$disp,
                     y=subset(df, am == 1)$disp,
                     weight=subset(df, am == 0)$wt,
                     weighty=subset(df, am == 1)$wt,
                     samedata=FALSE)
  out <<- ttest[2]
}

store <- do.call(rbind, sapply(df_list, multiple_wt_ttest))

报错的修改代码

library(tidyverse)
library(weights)
df_list <- split(mtcars, mtcars$carb)
var_list <- list("cyl","drat","disp")
multiple_wt_ttest <- function(df,var) {
  ttest = wtd.t.test(x=subset(df, am == 0)$var,
                     y=subset(df, am == 1)$var,
                     weight=subset(df, am == 0)$wt,
                     weighty=subset(df, am == 1)$wt,
                     samedata=FALSE)
  out <<- ttest[2]
}

store <- do.call(rbind, sapply(df_list,var=var_list, multiple_wt_ttest))

问题分析

  1. 变量引用错误:$var无法识别字符串形式的变量名,需改用[[var]]来解析字符串变量。
  2. 迭代参数传递问题:sapply仅支持单输入迭代,无法同时传入分组数据集和变量列表,需用嵌套迭代或组合迭代的方式处理。
  3. 全局变量副作用:使用out <<-修改全局变量不规范,应让函数直接返回结果,避免意外副作用。
  4. 空组未处理:部分carb分组下某am组可能无数据,直接运行检验会报错,需添加判断跳过此类情况。

解决方案

方案一:嵌套迭代(基于purrr)

利用tidyverse中的purrr包实现嵌套迭代,自动合并结果:

library(tidyverse)
library(weights)

# 修正后的检验函数:直接返回结构化结果
multiple_wt_ttest <- function(df, var) {
  # 提取两组数据
  group0 <- df %>% filter(am == 0)
  group1 <- df %>% filter(am == 1)
  
  # 跳过空组情况
  if(nrow(group0) == 0 || nrow(group1) == 0) {
    return(tibble(var = var, carb = unique(df$carb), statistic = NA, p_value = NA))
  }
  
  # 执行加权t检验
  ttest_result <- wtd.t.test(x = group0[[var]],
                             y = group1[[var]],
                             weight = group0$wt,
                             weighty = group1$wt,
                             samedata = FALSE)
  
  # 整理结果
  tibble(
    var = var,
    carb = unique(df$carb),
    statistic = ttest_result$coefficients[1],
    p_value = ttest_result$coefficients[2]
  )
}

# 定义分组和变量列表
carb_groups <- split(mtcars, mtcars$carb)
var_list <- c("cyl", "drat", "disp")

# 嵌套迭代:先遍历变量,再遍历每个carb分组
results <- map_dfr(var_list, function(var) {
  map_dfr(carb_groups, ~multiple_wt_ttest(.x, var))
})

# 查看最终结果
print(results)

方案二:组合迭代(基于expand.grid)

先生成所有carb值与变量的组合,再逐组执行检验:

library(tidyverse)
library(weights)

# 定义检验函数,直接接收carb值和变量名
multiple_wt_ttest <- function(carb_val, var, data = mtcars) {
  df <- data %>% filter(carb == carb_val)
  group0 <- df %>% filter(am == 0)
  group1 <- df %>% filter(am == 1)
  
  if(nrow(group0) == 0 || nrow(group1) == 0) {
    return(tibble(var = var, carb = carb_val, statistic = NA, p_value = NA))
  }
  
  ttest_result <- wtd.t.test(x = group0[[var]],
                             y = group1[[var]],
                             weight = group0$wt,
                             weighty = group1$wt,
                             samedata = FALSE)
  
  tibble(
    var = var,
    carb = carb_val,
    statistic = ttest_result$coefficients[1],
    p_value = ttest_result$coefficients[2]
  )
}

# 生成所有检验组合
test_combinations <- expand.grid(
  carb_val = unique(mtcars$carb),
  var = c("cyl", "drat", "disp"),
  stringsAsFactors = FALSE
)

# 逐组合执行检验并合并结果
results <- pmap_dfr(test_combinations, multiple_wt_ttest)

print(results)

关键改进点

  • 使用[[var]]正确解析字符串形式的变量名,替代无效的$var写法。
  • 移除全局变量,让函数直接返回整理好的tibble,避免副作用。
  • 添加空组判断,防止因某分组下无数据导致的报错。
  • 利用map_dfr/pmap_dfr自动合并结果,比do.call(rbind, ...)更简洁稳定。
  • 结果中保留var(待检验变量)和carb(分组)信息,便于后续分析。

内容的提问来源于stack exchange,提问作者flâneur

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 22:53:15