如何在R中按物种分组运行多个Mann Whitney U检验
解决方法
你的代码问题出在分组层级错误:同时按Species和BirthPop分组后,每个子组只包含单个物种的单个种群数据,此时无法在子组内进行BirthPop的组间比较,导致wilcox.test实际使用了整个数据集(或报错)。
以下是两种修正方案,都能实现每个物种独立的Mann-Whitney U检验,并保留各种群的描述统计:
方案一:分开计算后合并
library(dplyr) # 1. 计算每个物种的检验p值(仅按Species分组) wilcox_p_values <- data %>% group_by(Species) %>% summarize( wilcox_p = if(n_distinct(BirthPop) >= 2) { # 仅当物种包含至少两个种群时执行检验 wilcox.test(SexRatio ~ BirthPop, data = ., alternative = "two.sided")$p.value } else { NA # 单一种群时返回NA避免报错 }, .groups = "drop" ) # 2. 计算每个物种+种群的描述统计 summary_stats <- data %>% group_by(Species, BirthPop) %>% summarize( median = median(SexRatio), IQR = IQR(SexRatio), Min = min(SexRatio), Max = max(SexRatio), n = n(), .groups = "drop" ) # 3. 合并检验结果与描述统计 final_results <- summary_stats %>% left_join(wilcox_p_values, by = "Species")
方案二:用group_modify一次性处理
library(dplyr) final_results <- data %>% group_by(Species) %>% group_modify(function(sub_data, species_info) { # 计算当前物种的检验p值 p_val <- if(n_distinct(sub_data$BirthPop) >= 2) { wilcox.test(SexRatio ~ BirthPop, data = sub_data, alternative = "two.sided")$p.value } else { NA } # 生成当前物种内各种群的统计表格,并带上检验p值 sub_data %>% group_by(BirthPop) %>% summarize( median = median(SexRatio), IQR = IQR(SexRatio), Min = min(SexRatio), Max = max(SexRatio), n = n(), wilcox_p = p_val, .groups = "drop" ) }) %>% ungroup()
关键说明
- 两种方案都先按
Species单独分组,确保每个检验是在单个物种的所有种群数据上执行,得到该物种专属的p值。 - 加入
n_distinct(BirthPop) >=2的判断,是为了避免某些物种只有一种种群时,wilcox.test因数据不足报错。
内容的提问来源于stack exchange,提问作者JatNTU
相关产品推荐
相关产品推荐

