如何在参数值列表上进行“summarize”和/或“mutate”,而不需要外部“for”循环或生成额外的列?

问题描述 投票:0回答:1

我被要求生成这样的东西:

library("tidyverse")
df <- tibble(
  comparison_var = c(1:10), 
  var_to_sum = runif(10, max = 10), 
  other_var = runif(10, max = 50)
)

summary_tbl <- df |>
  summarize(
    other_summary = mean(other_var),
    sum_gt1 = sum((comparison_var > 2) * var_to_sum),
    sum_gt2 = sum((comparison_var > 3) * var_to_sum),
    #...,
    sum_gtN = sum((comparison_var > 9) * var_to_sum)
  )

无需重复。换句话说,生成使用(单个)简单变化参数值计算的任意数量的列。从技术上讲,我已经知道一些完成此任务的方法:

  • 我可以创建 N 列,例如虚拟人先指示
    (comparison_var > n)
    ,然后指示
    across(starts_with(...), ...)
    • 即使这样也引出了一个问题,即如何生成那些不将 mutate 粘在
      for
      循环或
      apply
      /
      map
      调用中的情况? IE。可以在管链中完成循环吗,inside
      mutate(...)
  • 我可以将
    summarize()
    放入循环中,
    for (cutoff in 1:N) {...}
    ,我想
    _join()
    将结果放入现有的汇总表中。
  • 我大概可以再次使用每个参数值创建列,或者可能更复杂地创建一个包含参数列表的列表列,然后再次使用
    across()
    ,或者一些可能返回数据帧的
    map
    /
    apply
    东西.

其中一些并不是非常不雅,但确实感觉这应该是超级基本的东西。它与

across()
的想法完全相同,除了跨外部向量而不是多个列。事实上,每次我尝试用谷歌搜索它时,我发现的都是有关如何使用的问题
across

我真的很想要一些不涉及生成额外的列,或循环,或者实际上,理想情况下,留下管道链的东西。

我确实注意到,

summarize()
mutate()
的值本身可以是一个小标题,一次生成多个列。这导致写下这篇文章:

worldpop_educ_splits <- merged_tbl |>
  summarize(
    across(
      starts_with("yr_sch_gt"),
      ~ sum(.x * pop, na.rm = TRUE) / sum(pop, na.rm = TRUE),
      .names = "fracwt_{.col}"
    ),
    {
      tbl <- tibble(.rows = 1)
      for (cutoff in 2:9) {
        tbl[[1, glue("fracwt_yrsch_gt{cutoff}")]] <-
          sum((yr_sch > cutoff) * pop, na.rm = TRUE) / sum(pop, na.rm = TRUE)
      }
      tbl
    },
    .by = year
  )

这在技术上可行,但令人憎恶,而且,正如你可以猜到的那样,速度非常慢。我在示例中保留了第一个

across()
调用,因为它与我想要在第二个调用中执行的计算相同,但对于一个变量,我已经为每个截止级别提供了一个指示器。我只是不想也为这个制定一个指标,并且也想停止为第一个这样做。

是的,我可以改变一些列,然后将它们删除,或者用

summarize()
让它们消失。只是感觉必须有一种非常明显、优雅的方式来做到这一点,但我缺少。

非常感谢您的投入!

r dplyr tidyverse refactoring summarize
1个回答
0
投票

我并不关心计算速度,但对于这类事情我通常会得到一些

purrr
魔法:

library(tidyverse)
df %>%
  summarize(other_summary = mean(other_var)) %>%
  bind_cols(.x = map(1:9,
            .f = ~df %>%

summarize(!!sym(paste0('sum_gt', .x)) := sum((comparison_var > .x) * var_to_sum))) %>% 绑定_列())

# A tibble: 1 x 10
  other_summary sum_gt1 sum_gt2 sum_gt3 sum_gt4 sum_gt5 sum_gt6 sum_gt7 sum_gt8
          <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
1          29.0    39.8    34.5    34.4    27.1    21.2    20.8    15.6    14.3
# ... with 1 more variable: sum_gt9 <dbl>
© www.soinside.com 2019 - 2024. All rights reserved.