如何为数据框每行执行双比例prop.test?为何p值一致?
问题描述
我想要检验基线(Baseline)与终线(Endline)的比例差异,数据如下:
group n_Baseline n_Endline sample_Baseline sample_Endline <chr> <int> <int> <dbl> <dbl> 1 A 164 158 305 273 2 B 89 65 131 106 3 C 59 68 118 108 4 D 52 48 90 84 5 E 141 107 224 186
我尝试用以下代码计算每行的p值:
df$P_Values <- apply(df, 1, function(x) prop.test(x = c(df$n_Baseline, df$n_Endline), n = c(df$sample_Baseline, df$sample_Endline))$p.value)
结果所有行的p值均为0.109:
group n_Baseline n_Endline sample_Baseline sample_Endline P_Values <chr> <int> <int> <dbl> <dbl> <dbl> 1 A 164 158 305 273 0.109 2 B 89 65 131 106 0.109 3 C 59 68 118 108 0.109 4 D 52 48 90 84 0.109 5 E 141 107 224 186 0.109
但单独计算每行时p值差异很大,例如第一行执行:
prop.test(x = c(164, 158), n = c(305, 273))
得到的p值为0.3639。请问为何会出现这种情况?如何获取每行对应的准确p值?
问题原因
你在apply的匿名函数中错误引用了整个数据框的列(df$n_Baseline、df$sample_Baseline等),而非当前行的对应值。这导致每次循环都在对所有行的合并数据执行比例检验,而非单独处理每行数据,因此所有行得到的都是同一整体数据的检验结果,p值完全相同。
解决方法
方法1:修正apply的匿名函数
在apply的函数内部,通过x提取当前行的元素(注意apply处理数据框时会将行转为字符向量,需先转换类型):
df$P_Values <- apply(df, 1, function(x) { # 提取当前行的数值并转换类型 n_baseline <- as.integer(x["n_Baseline"]) n_endline <- as.integer(x["n_Endline"]) sample_baseline <- as.numeric(x["sample_Baseline"]) sample_endline <- as.numeric(x["sample_Endline"]) # 执行比例检验 prop.test(x = c(n_baseline, n_endline), n = c(sample_baseline, sample_endline))$p.value })
方法2:使用dplyr逐行处理(更直观)
借助dplyr的rowwise()函数实现逐行操作:
library(dplyr) df <- df %>% rowwise() %>% mutate(P_Values = prop.test(x = c(n_Baseline, n_Endline), n = c(sample_Baseline, sample_Endline))$p.value) %>% ungroup()
方法3:使用purrr的pmap函数
通过purrr的pmap_dbl按行映射参数,代码更简洁:
library(purrr) df$P_Values <- pmap_dbl(df[, c("n_Baseline", "n_Endline", "sample_Baseline", "sample_Endline")], function(nB, nE, sB, sE) prop.test(x = c(nB, nE), n = c(sB, sE))$p.value)
内容的提问来源于stack exchange,提问作者Kim Nguyen
相关产品推荐
相关产品推荐

