R语言中数据框子集多组加权t检验的报错排查
问题描述
我正在R中编写代码,想要对数据框的不同子集执行多组加权t检验,初始代码如下:
library(weights) group_list <- list(unique(df$group)) t_tests <- for (g in group_list){wtd.t.test(x=df[df$group == g,]$var2[df[df$group == g,]$var1=="A"],y=df[df$group == g,]$var2[df[df$group == g,]$var1=="B"], weight=df[df$group == g,]$weight[df[df$group == g,]$var1=="A"],weighty=df[df$group == g,]$weight[df[df$group == g,]$var1=="B"],samedata=FALSE)}
其中var2是关注的结果变量,我希望检验var1="A"和var1="B"的均值差异显著性,并针对group变量的不同取值对每个数据子集执行该检验。
运行上述代码时出现错误:
Error in wtd.t.test(x = df[df$group == g, : object 'out' not found
想确认是不是函数结构有误?该如何实现对数据框每个子集执行加权t检验?
更新1:尝试嵌套tibbles方法
改用tidyverse的嵌套数据框方法,代码如下:
library(weights) library(tidyverse) df %>% nest(-group) %>% mutate(fit = map(data, ~ wtd.t.test(x=.%>%filter(var1 == "A")$var2,y=.%>% filter(var1 == "B")$var2, weight=.%>% filter(var1 == "A")$weight,weighty=.%>% filter(var1 == "B")$weight,samedata=FALSE)), results = map(fit, glance)) %>% unnest(results)
报错信息:
Error in `mutate()`: ℹ In argument: `fit = map(...)`. Caused by error in `map()`: ℹ In index: 1. Caused by error in `weight / mean(weight, na.rm = TRUE)`: ! non-numeric argument to binary operator Backtrace: 1. ... %>% unnest(results) 10. purrr::map(...) 11. purrr:::map_("list", .x, .f, ..., .progress = .progress) 15. .f(.x[[i]], ...) 16. weights::wtd.t.test(...)
除Var1外所有变量均为数值型,Var1不参与计算,不清楚为何出现该错误,求解决方案。
若将代码改写为:
df %>% nest(-country) %>% mutate(fit = map(data, ~ wtd.t.test(x=filter(.,var1 == "A")$var2,y=filter(.,var1 == "B")$var2, weight=filter(.,var1 == "A")$weight,weighty=filter(.,var1 == "B")$weight,samedata=FALSE)), results = map(fit, glance)) %>% unnest(results)
报错变为:
Error in `mutate()`: ℹ In argument: `fit = map(...)`. Caused by error in `map()`: ℹ In index: 1. Caused by error in `wtd.t.test()`: ! object 'out' not found Backtrace: 1. ... %>% unnest(results) 10. purrr::map(...) 11. purrr:::map_("list", .x, .f, ..., .progress = .progress) 15. .f(.x[[i]], ...) 16. weights::wtd.t.test(...)
更新2:可复现代码示例
用mtcars数据集测试的代码如下:
library(weights) library(tidyverse) mtcars %>% nest(-cyl) %>% mutate(fit = map(data, ~ wtd.t.test(x=.%>%filter(gear == 3)$disp,y=.%>% filter(gear = 4)$disp, weight=.%>% filter(gear == 3)$wt,weighty=.%>% filter(gear == 4)$wt,samedata=FALSE)), results = map(fit, glance)) %>% unnest(results)
改写后的代码:
mtcars %>% nest(-cyl) %>% mutate(fit = map(data, ~ wtd.t.test(x=filter(.,gear == 3)$disp,y=filter(.,gear == 4)$disp, weight=filter(.,gear == 3)$weight,weighty=filter(.,gear == 4)$weight,samedata=FALSE)), results = map(fit, glance)) %>% unnest(results)
解决方案
1. 初始循环代码的修正
group_list <- list(unique(df$group))会把整个分组向量塞进一个列表元素,导致循环仅执行一次,应改为group_list <- unique(df$group)直接遍历分组值。- 循环无法直接赋值给变量,需预先创建列表存储每个检验结果。
修正后的循环代码:
library(weights) group_list <- unique(df$group) t_tests <- list() for (g in group_list) { # 提取当前分组的子集 sub_df <- df[df$group == g, ] # 分别筛选A和B组的数据 a_data <- sub_df[sub_df$var1 == "A", ] b_data <- sub_df[sub_df$var1 == "B", ] # 执行加权t检验,跳过空子集避免报错 if (nrow(a_data) > 0 && nrow(b_data) > 0) { t_tests[[as.character(g)]] <- wtd.t.test( x = a_data$var2, y = b_data$var2, weight = a_data$weight, weighty = b_data$weight, samedata = FALSE ) } } # 查看结果 t_tests
2. 嵌套tibbles方法的修正
核心问题:
- 管道语法错误:
.%>%filter(...)写法无效,应使用filter(., ...); - 变量名不匹配:mtcars中无
weight变量,需用wt; broom::glance()不支持weights::wtd.t.test返回对象,需手动提取结果。
修正后的嵌套代码:
library(weights) library(tidyverse) # 定义提取加权t检验结果的函数 extract_wtd_t_result <- function(test_obj) { if (is.null(test_obj)) { return(tibble(mean_x = NA, mean_y = NA, t_stat = NA, df = NA, p_value = NA, se_diff = NA)) } tibble( mean_x = test_obj$additional[["mean.x"]], mean_y = test_obj$additional[["mean.y"]], t_stat = test_obj$coefficients[["t.value"]], df = test_obj$coefficients[["df"]], p_value = test_obj$coefficients[["p.value"]], se_diff = test_obj$coefficients[["Std. Error"]] ) } # mtcars测试的修正代码 mtcars %>% nest(data = -cyl) %>% mutate( fit = map(data, function(sub_df) { a_data <- filter(sub_df, gear == 3) b_data <- filter(sub_df, gear == 4) # 跳过空子集 if (nrow(a_data) == 0 || nrow(b_data) == 0) { return(NULL) } wtd.t.test( x = a_data$disp, y = b_data$disp, weight = a_data$wt, weighty = b_data$wt, samedata = FALSE ) }), results = map(fit, extract_wtd_t_result) ) %>% unnest(results)
关键注意事项
- 确保每个分组下
var1="A"和var1="B"都有有效数据,否则需添加判断跳过空子集; weights::wtd.t.test返回的对象结构特殊,无法直接用broom系列函数解析,需手动提取统计量;- 变量名需严格匹配数据集,避免出现“变量不存在”的隐性错误。
内容的提问来源于stack exchange,提问作者flâneur
相关产品推荐
相关产品推荐

