在dplyr mutate中结合purrr map,按列值动态选择列应用函数
解决dplyr mutate中根据列值选择目标列应用函数的问题
问题背景
需要在dplyr的mutate上下文里,根据selector列的取值,对每行对应的目标列(a或b)应用自定义平方函数calc,生成quad列。测试数据和函数如下:
test <- data.frame(a = c(1,2), b = c(3,4), selector = c("a","b")) calc <- function(col) { res <- col ^ 2 return(res) }
错误原因
原代码mutate(quad = map(.data[[selector]], ~ calc(.x)))出错,是因为.data[[selector]]试图用整个selector向量作为索引取列,无法实现逐行匹配不同列名的需求,且map的迭代逻辑不适合这种行级的列选择场景。
解决方案
方案1:使用rowwise() + cur_data()
这是最直观的tidyverse风格方案,通过rowwise()让dplyr按行处理,cur_data()获取当前行的数据集,再用[[selector]]取出对应列的值:
test %>% rowwise() %>% mutate(quad = calc(cur_data()[[selector]])) %>% ungroup()
方案2:使用purrr::pmap_dbl
pmap系列函数支持按行迭代数据框,每行元素作为参数传入自定义逻辑:
test %>% mutate(quad = pmap_dbl(., function(...) { row <- tibble(...) calc(row[[row$selector]]) }))
方案3:Base R 实现
用mapply结合索引矩阵实现逐行取值计算:
test$quad <- mapply( function(val) calc(val), val = test[cbind(seq(nrow(test)), match(test$selector, names(test)))] )
验证结果
三种方案都能得到预期输出:
a b selector quad 1 1 3 a 1 2 2 4 b 16
内容的提问来源于stack exchange,提问作者taxecron
相关产品推荐
相关产品推荐

