使用箱线图时无法计算带结精确p值的技术咨询
我有多个癌症数据集,以基因为行、样本为列,每个数据集包含标记为Response的治疗响应样本和NoResponse的无响应样本。我想用带facet_wrap的箱线图,结合Wilcoxon检验,分析每个数据集里两组样本的关键基因表达差异,但运行代码时出现了一系列警告,且发现有39行数据被移除(但我确认数据中没有非有限值)。想搞清楚这些警告的含义,以及Wilcoxon检验里的“带结(ties)”是什么意思。
运行时警告
Warning messages: 1: Removed 39 rows containing non-finite values (stat_signif). 2: In wilcox.test.default(c(1904, 736, 26, 43, 420, 336, 105, 569, : cannot compute exact p-value with ties 3: In wilcox.test.default(c(162, 23, 94, 25, 22, 1, 19, 148, 76, 48, : cannot compute exact p-value with ties 4: In wilcox.test.default(c(0.0143552929770701, 0.739848102699327, : cannot compute exact p-value with ties 5: In wilcox.test.default(c(110, 204, 164, 437), c(33, 15, 239, 65, : cannot compute exact p-value with ties 6: In wilcox.test.default(c(14, 96, 8, 31, 89, 1, 168, 20, 574, 0, : cannot compute exact p-value with ties 7: Removed 39 rows containing non-finite values (stat_boxplot). 8: Position guide is perpendicular to the intended axis. Did you mean to specify a different guide `position`?
所用R函数代码
showgene <- function(gene) { dt = data.frame(expr=c(t(dataset1[gene,]),t(dataset2[gene,]), t(dataset3[gene,]),t(dataset4[gene,]), t(dataset5[gene,]),t(dataset6[gene,]),t(dataset7[gene,]),t(dataset8[gene,]),t(dataset9[gene,]) ,t(dataset10[gene,]),t(dataset11[gene,]),t(dataset12[gene,]),t(dataset13[gene,]),t(dataset15[gene,]), t(dataset16[gene,]) ,t(dataset20[gene,]),t(dataset21[gene,])), response=Response, dataSet=c(rep('data1',ncol(dataset1)), rep('data2',ncol(dataset2)), rep('data3',ncol(dataset3)), rep('data4',ncol(dataset4)), rep('data5',ncol(dataset5)), rep('data6',ncol(dataset6)), rep('data7',ncol(dataset7)), rep('data8',ncol(dataset8)), rep('data9',ncol(dataset9)), rep('data10',ncol(dataset10)), rep('data11',ncol(dataset11)), rep('data12',ncol(dataset12)), rep('data13',ncol(dataset13)), rep('data15',ncol(dataset15)), rep('data16',ncol(dataset16)), rep('data20',ncol(dataset20)), rep('data21',ncol(dataset21)))) dt[['expr']] = as.numeric(as.character(dt[['expr']])) facetplot = dt %>% ggplot(aes(response, expr, fill = response)) + facet_wrap(~dataSet, scales = 'free') + labs(x = 'Clinical outcome', y = 'Expression') + ggtitle(gene) + theme(plot.title = element_text(hjust = 0.5)) + stat_compare_means(comparisons = my_comparisons, vjust = 1.2, method = "wilcox.test") boXplots = facetplot + geom_boxplot() return(boXplots) } showgene('CD274')
数据集示例(dt)
structure(list(expr = c(1484, 290, 1421, 251, 203, 888, 608, 1203, 1340, 1021, 182, 170, 291, 401, 140, 117, 582, 1177, 191, 152, 111, 24, 187, 705, 1122, 694, 224, 1122, 501, 268, 1277, 270, 705, 276, 88, 157, 2564, 25, 251, 255, 484, 96, 37, 180, 169, 949, 1477, 128, 321, 32.164880027492, 30.5002842845929, 30.3194383690632, 31.2055296895404, 31.9247612316469, 30.6333196961515, 30.0292937311801, 30.9803064773279, 30.0890307092925, 31.6247367596842, 30.2033356286348), response = c("NoResponse", "NoResponse", "Response", "NoResponse", "NoResponse", "NoResponse", "NoResponse", "Response", "NoResponse", "NoResponse", "NoResponse", "NoResponse", "NoResponse", "NoResponse", "Response", "Response", "NoResponse", "Response", "NoResponse", "NoResponse", "NoResponse", "NoResponse", "NoResponse", "Response", "NoResponse", "NoResponse", "Response", "Response", "NoResponse", "NoResponse", "NoResponse", "NoResponse", "NoResponse", "NoResponse", "NoResponse", "Response", "NoResponse", "NoResponse", "NoResponse", "NoResponse", "NoResponse", "NoResponse", "NoResponse", "NoResponse", "NoResponse", "NoResponse", "NoResponse", "Response", "NoResponse", "Response", "NoResponse", "NoResponse", "NoResponse", "Response", "Response", "NoResponse", "NoResponse", "Response", "Response", "NoResponse"), dataSet = c("data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data1", "data2", "data2", "data2", "data2", "data2", "data2", "data2", "data2", "data2", "data2", "data2")), row.names = c(NA, 60L), class = "data.frame")
1. 关于“移除39行含非有限值”的警告(警告1、7)
你确认数据里没有NA、NaN或Inf,但出现这个警告,大概率是类型转换失败导致的隐性非有限值:
- 你用了
dt[['expr']] = as.numeric(as.character(dt[['expr']])),如果原始expr列里有无法转成数值的字符串(比如空字符串、非数字字符),转换后会变成NA,这些NA就会被ggplot的stat_signif和stat_boxplot识别为非有限值并移除。 - 另外检查
Response向量和各个数据集的样本数是否匹配:你手动拼接response=Response,如果Response的长度和所有数据集的总样本数(sum(ncol(dataset1),ncol(dataset2),...))不一致,会导致循环填充,可能引入异常值,进而在转换或绘图时被判定为非有限值。
2. Wilcoxon检验的“带结(ties)”警告(警告2-6)
什么是“结(ties)”?
在Wilcoxon秩和检验(Mann-Whitney U检验)中,结指的是两组数据中存在相同的数值。比如你的表达数据里,不同样本的基因表达量完全一样,这就是结。
为什么会出现这个警告?
Wilcoxon检验的精确p值计算依赖于所有观测值都是唯一的假设——因为它基于秩的排列组合。当有结存在时,精确的排列组合数无法准确计算,所以R会提示无法计算精确p值,转而使用近似方法(正态近似)来计算p值,这个近似结果依然是有效的,只是不是“精确”值而已。
3. 位置指南方向错误的警告(警告8)
这个警告来自stat_compare_means的标注位置设置:你用了vjust=1.2,但因为x轴是分类变量(response是两组),vjust控制的是垂直方向位置,而标注可能需要水平调整(hjust),或者stat_compare_means的默认位置和你的绘图方向不匹配。可以尝试调整position参数,比如设置position = position_dodge(width = 0.8),或者改用hjust来调整标注位置。
解决建议
- 排查数据转换问题:运行
sum(is.na(dt$expr))查看有多少NA,再检查原始数据集的expr列是否有非数字内容;同时验证length(Response)是否等于sum(sapply(list(dataset1,dataset2,...),ncol)),确保样本数匹配。 - 处理Wilcoxon的结问题:如果想消除警告,可以在
wilcox.test里添加exact=FALSE参数,明确告诉R使用近似方法。在stat_compare_means里可以通过method.args = list(exact = FALSE)来传递这个参数:stat_compare_means(comparisons = my_comparisons, vjust = 1.2, method = "wilcox.test", method.args = list(exact = FALSE)) - 修正位置警告:调整
stat_compare_means的位置参数,比如:stat_compare_means(comparisons = my_comparisons, hjust = 0.5, method = "wilcox.test", method.args = list(exact = FALSE))
内容的提问来源于stack exchange,提问作者Programming Noob

