R语言tidyverse如何参数化实现单列多四分位数汇总输出
参数化实现单列多汇总值列向输出
问题说明
- 现有tibble数据集,需要对同一列计算第一、第二、第三四分位数三个汇总统计值
- 硬编码命名函数列表的方式可正常实现需求,代码及运行结果如下:
library("tidyverse") set.seed(1234) df <- tibble(x = rnorm(100)) df %>% summarise( across(x, list( Q1 = ~ quantile(., 1 / 4), Q2 = ~ quantile(., 2 / 4), Q3 = ~ quantile(., 3 / 4) ), .names = "{.fn}" ) )
#> # A tibble: 1 × 3 #> Q1 Q2 Q3 #> <dbl> <dbl> <dbl> #> 1 -0.895 -0.385 0.471
- 优化目标:直接给
quantile传入概率参数列表实现效果,减少重复代码,避免硬编码聚合函数参数 - 直接传参的错误写法会按概率值逐行输出结果,无法生成单独的分位数列,代码及运行结果如下:
df %>% summarise( across(x, quantile, 1:3 / 4) )
#> # A tibble: 3 × 1 #> x #> <dbl> #> 1 -0.895 #> 2 -0.385 #> 3 0.471
- 错误原因:直接调用
quantile(x, 1:3/4)会返回长度为3的数值向量,summarise默认将长度大于1的非列表返回值拆分为多行,因此得到3行1列的输出。
实现方案
方案1:参数化生成命名函数列表(推荐,最贴合across原生用法)
提前定义带命名的分位数概率向量,后续调整分位点只需要修改该向量即可,通过purrr::map配合purrr::partial预填充quantile的概率参数,自动生成across需要的命名函数列表:
# 统一配置需要计算的分位点,可按需增删修改 probs <- c(Q1 = 1/4, Q2 = 2/4, Q3 = 3/4) df %>% summarise( across(x, map(probs, ~partial(quantile, probs = .x, names = FALSE)), .names = "{.fn}" ) )
运行结果和硬编码写法完全一致:
#> # A tibble: 1 × 3 #> Q1 Q2 Q3 #> <dbl> <dbl> <dbl> #> 1 -0.895 -0.385 0.471
方案2:列表列+宽表拆分
先将分位数计算结果存入列表列(此时summarise仅返回1行),再将列表列拆分为独立列:
probs <- c(Q1 = 1/4, Q2 = 2/4, Q3 = 3/4) df %>% summarise(x = list(quantile(x, probs, names = FALSE))) %>% unnest_wider(x, names_repair = ~names(probs))
运行结果和上述方案一致。
内容的提问来源于stack exchange,提问作者dipetkov
相关产品推荐
相关产品推荐

