我被要求生成这样的东西:
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)
)
无需重复。换句话说,生成使用(单个)简单变化参数值计算的任意数量的列。从技术上讲,我已经知道一些完成此任务的方法:
(comparison_var > n)
,然后指示 across(starts_with(...), ...)
。
for
循环或 apply
/map
调用中的情况? IE。可以在管链中完成循环吗,insidemutate(...)
?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()
让它们消失。只是感觉必须有一种非常明显、优雅的方式来做到这一点,但我缺少。
非常感谢您的投入!
我并不关心计算速度,但对于这类事情我通常会得到一些
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>