tbl_summary调用add_p无法获取卡方p值报fisher.test错误如何解决
问题描述
需生成指定结构的分组统计表,要求如下:
- 分组变量为
ethnicity,共分Ethnicity A、Ethnicity B、Ethnicity C三组 - 行维度为
CD_loc的3个有效分类,加Missing缺失分类,总样本量约34000例 - 表格需展示缺失值的例数,但卡方检验计算时排除缺失数据,最终输出组间比较的卡方检验p值
- 目标表格结构:
| Ethnicity A | Ethnicity B | Ethnicity C | |
|---|---|---|---|
| CD_loc 1 | 456 | 555 | 348 |
| CD_loc 2 | 452 | 158 | 257 |
| CD_loc 3 | 50 | 18 | 58 |
| Missing | 3 | 4 | 8 |
初始使用的R代码如下:
meta1_CD %>% select(ethnicity,CD_loc) %>% tbl_summary( by = ethnicity, statistic = list(all_continuous() ~ "{mean} ({sd})", all_categorical() ~ "{n} ({p}%)"), digits = all_continuous() ~ 1, type = all_categorical() ~ "categorical", missing_text = "Missing") %>% add_p()
运行后未正常输出p值,收到如下报错,CD_loc对应的p值被自动省略:
There was an error in 'add_p()/add_difference()' for variable 'CD_loc', p-value omitted:
Error in stats::fisher.test(structure(c(6L, 1L, 5L, 1L, 1L, 3L, 1L, 1L, : Bug in fexact3, it[i=4]=0: negative key -1556839370 (kyy=13301)
报错原因
gtsummary的add_p()函数默认会根据列联表特征自动选择检验方法:当表中存在极小频数单元格(如示例中Missing行三组例数仅为3、4、8)时,会默认调用Fisher精确检验。你遇到的fexact3报错是R内置fisher.test()在处理大样本、稀疏高维列联表时的已知底层Fortran程序bug,3.4万的大样本量本身也不适合用Fisher精确检验。- 默认逻辑会将表格中展示的Missing分类纳入检验计算,不符合“检验时排除缺失值”的需求。
解决方法
按以下两步调整代码即可:
- 显式指定使用Pearson卡方检验,避免触发Fisher检验的底层bug,大样本场景下卡方检验的适用性完全满足统计要求
- 自定义检验逻辑,在计算p值时过滤掉
CD_loc为Missing的记录,同时保留表格中的缺失值展示
调整后的可运行代码如下:
library(gtsummary) library(tidyverse) # 自定义卡方检验函数:检验时排除CD_loc缺失的记录 chisq_exclude_missing <- function(data, variable, by, ...) { # 过滤掉CD_loc为缺失的记录 test_data <- data %>% filter(!is.na(.data[[variable]])) # 构建列联表执行无连续性校正的Pearson卡方检验 tab <- table(test_data[[variable]], test_data[[by]]) res <- chisq.test(tab, correct = FALSE) # 返回gtsummary要求的标准结果格式 tibble( p = res$p.value, method = "Pearson's Chi-squared test" ) } # 生成最终统计表 meta1_CD %>% select(ethnicity, CD_loc) %>% tbl_summary( by = ethnicity, # 若只需要展示例数,将统计量改为"{n}"即可,和示例目标表完全匹配 statistic = list(all_categorical() ~ "{n}"), type = all_categorical() ~ "categorical", # 表格中保留缺失值行,命名为Missing missing = "ifany", missing_text = "Missing" ) %>% add_p( # 指定CD_loc使用自定义的卡方检验,排除缺失值 test = list(CD_loc ~ chisq_exclude_missing), # 可自定义p值小数位数 pvalue_fun = ~style_pvalue(.x, digits = 3) )
补充说明
- 如果需要同时展示例数和百分比,将
statistic参数的"{n}"改回"{n} ({p}%)"即可 - 如果需要使用带Yates连续性校正的卡方检验,将
chisq.test()里的correct = FALSE改为correct = TRUE即可
内容的提问来源于stack exchange,提问作者Sharmili Balarajah
相关产品推荐
相关产品推荐

