dplyr::mutate函数行为异常求助:添加binom检验p值失败
问题根源:
binom.test不支持向量化输入 你遇到的问题核心在于两个函数的向量化能力本质不同:
- 你的
my_add函数依赖的是R原生的+运算符,它本身就是向量化设计——当传入两个向量时,会自动对每个位置的元素逐一计算,这也是它能在mutate里正常工作的原因。 - 但
binom.test是为单个样本设计的统计函数,它完全不支持向量输入。当你把向量传给它的x和n参数时,它不会逐个处理元素,反而会尝试把整个向量当作单个输入来处理,这就导致了两种异常:- 当数据框有2行时,
binom.test可能只处理了第一组元素对,然后把结果重复返回(所以两行的p值完全一致); - 当数据框有3行时,
binom.test无法处理长度为3的向量输入,直接抛出"incorrect length of 'x'"的错误。
- 当数据框有2行时,
解决方案:让函数支持向量化
有几种简单的方法可以解决这个问题,让你的my_binom函数能在mutate里正常工作:
方法1:用purrr::map2_dbl逐行计算
purrr包的map2_dbl可以对两个向量的对应元素逐一应用函数,并返回数值向量,完美适配mutate的需求:
library(dplyr) library(purrr) my_binom <- function(x, y) binom.test(x, y)$p.value df <- data.frame(success=c(5,8,4), total=c(20,21,22)) df %>% mutate(p_value = map2_dbl(success, total, my_binom)) #> success total p_value #> 1 5 20 0.0413881 #> 2 8 21 0.2427668 #> 3 4 22 0.0250576
方法2:用Vectorize包装函数
R内置的Vectorize函数可以快速把非向量化的函数包装成向量化版本,不需要额外依赖其他包:
my_binom_vec <- Vectorize(function(x, y) binom.test(x, y)$p.value) df %>% mutate(p_value = my_binom_vec(success, total)) #> success total p_value #> 1 5 20 0.0413881 #> 2 8 21 0.2427668 #> 3 4 22 0.0250576
方法3:用rowwise()让dplyr逐行处理
可以先用rowwise()把数据框转为逐行处理的模式,这样mutate就会对每一行单独调用函数,处理完记得取消逐行模式避免后续操作变慢:
df %>% rowwise() %>% mutate(p_value = my_binom(success, total)) %>% ungroup() #> # A tibble: 3 × 3 #> success total p_value #> <dbl> <dbl> <dbl> #> 1 5 20 0.0414 #> 2 8 21 0.243 #> 3 4 22 0.0251
额外说明
为什么2行的时候没有报错但返回错误结果?这是因为binom.test在接收向量时,会尝试用整个向量作为输入——比如当你传入x=c(5,8)和n=c(20,21)时,它其实是在做一个逻辑错误的二项式检验(把向量当作单一输入),而这个错误的输入刚好没有触发严格的长度检查,所以它把这个错误计算的结果重复填充到了每一行。
内容的提问来源于stack exchange,提问作者heathobrien
相关产品推荐
相关产品推荐

