Dplyr 多个管道动态变量?
Dplyr multiple piped dynamic variables?
我经常这样做:
library(tidyverse)
iris %>%
group_by(Species) %>%
summarise(num_Species = n_distinct(Species)) %>%
mutate(perc_Species = 100 * num_Species / sum(num_Species))
所以我想创建一个输出相同内容但具有动态命名的 num_ 和 perc_ 列的函数:
num_perc <- function(df, group_var, summary_var) {
}
我发现 this resource 很有用,但它没有直接说明如何以我想要的方式重用新创建的列名。
您可以做的是在 group_var
上使用 as_label(enquo())
提取作为字符向量传递的变量以生成新列。您可以在您发送的链接文档中看到一个明显的例子 6.1.3。通过这种方式,我们可以动态地将 num_
和 perc_
添加到您的摘要变量中,只需传入 df
和 group_var
.
library(dplyr)
num_perc <- function(df, group_var) {
summary_lbl <- as_label(enquo(group_var))
num_lbl <- paste0("num_", summary_lbl)
perc_lbl <- paste0("perc_", summary_lbl)
df %>%
group_by({{ group_var }}) %>%
summarize(!!num_lbl := n_distinct({{ group_var }})) %>%
mutate(!!perc_lbl := 100 * .data[[num_lbl]] / sum(.data[[num_lbl]]))
}
num_perc(iris, Species)
#> # A tibble: 3 × 3
#> Species num_Species perc_Species
#> <fct> <int> <dbl>
#> 1 setosa 1 33.3
#> 2 versicolor 1 33.3
#> 3 virginica 1 33.3
在这种情况下,group_var
和 summary_var
实际上不同,但本质上是相同的解决方案。
num_perc <- function(df, group_var, summary_var) {
summary_lbl <- as_label(enquo(summary_var))
num_lbl <- paste0("num_", summary_lbl)
perc_lbl <- paste0("perc_", summary_lbl)
df %>%
group_by({{ group_var }}) %>%
summarize(!!num_lbl := n_distinct({{ summary_var }})) %>%
mutate(!!perc_lbl := 100 * .data[[num_lbl]] / sum(.data[[num_lbl]]))
}
num_perc(iris, Species, Species)
您确定 n_distinct 是您想要的吗?在鸢尾花数据集的情况下,有三个物种 - setosa、versicolor、virginica。因此,每个物种都是 1/3 独特的物种。 Iris 数据集是平衡的,因为每个物种有 50 个,因此每个物种代表数据集的 1/3,但更普遍的情况并非如此。
具有数据屏蔽功能的函数将为您覆盖不平衡的数据集:
library(dplyr)
my_func <- function(df, var, percent){
df %>%
count({{var}}) %>%
mutate(percent = 100 * n/sum(n))
}
my_func(iris, Species, percent)
iris %>%
my_func(Species, percent) #or with pipe
另一种可能的解决方案,它使用 deparse(substitute(...))
将函数参数的名称作为字符串获取:
library(tidyverse)
f <- function(df, group_var, summary_var)
{
group_var <- deparse(substitute(group_var))
summary_var <- deparse(substitute(summary_var))
df %>%
group_by(!!sym(group_var)) %>%
summarise(!!str_c("num_", summary_var) := n_distinct(summary_var)) %>%
mutate(!!str_c("per_", summary_var) := 100 * !!sym(str_c("num_", summary_var)) / sum(!!sym(str_c("num_", summary_var))))
}
f(iris, Species, Species)
#> # A tibble: 3 × 3
#> Species num_Species per_Species
#> <fct> <int> <dbl>
#> 1 setosa 1 33.3
#> 2 versicolor 1 33.3
#> 3 virginica 1 33.3
我经常这样做:
library(tidyverse)
iris %>%
group_by(Species) %>%
summarise(num_Species = n_distinct(Species)) %>%
mutate(perc_Species = 100 * num_Species / sum(num_Species))
所以我想创建一个输出相同内容但具有动态命名的 num_ 和 perc_ 列的函数:
num_perc <- function(df, group_var, summary_var) {
}
我发现 this resource 很有用,但它没有直接说明如何以我想要的方式重用新创建的列名。
您可以做的是在 group_var
上使用 as_label(enquo())
提取作为字符向量传递的变量以生成新列。您可以在您发送的链接文档中看到一个明显的例子 6.1.3。通过这种方式,我们可以动态地将 num_
和 perc_
添加到您的摘要变量中,只需传入 df
和 group_var
.
library(dplyr)
num_perc <- function(df, group_var) {
summary_lbl <- as_label(enquo(group_var))
num_lbl <- paste0("num_", summary_lbl)
perc_lbl <- paste0("perc_", summary_lbl)
df %>%
group_by({{ group_var }}) %>%
summarize(!!num_lbl := n_distinct({{ group_var }})) %>%
mutate(!!perc_lbl := 100 * .data[[num_lbl]] / sum(.data[[num_lbl]]))
}
num_perc(iris, Species)
#> # A tibble: 3 × 3
#> Species num_Species perc_Species
#> <fct> <int> <dbl>
#> 1 setosa 1 33.3
#> 2 versicolor 1 33.3
#> 3 virginica 1 33.3
在这种情况下,group_var
和 summary_var
实际上不同,但本质上是相同的解决方案。
num_perc <- function(df, group_var, summary_var) {
summary_lbl <- as_label(enquo(summary_var))
num_lbl <- paste0("num_", summary_lbl)
perc_lbl <- paste0("perc_", summary_lbl)
df %>%
group_by({{ group_var }}) %>%
summarize(!!num_lbl := n_distinct({{ summary_var }})) %>%
mutate(!!perc_lbl := 100 * .data[[num_lbl]] / sum(.data[[num_lbl]]))
}
num_perc(iris, Species, Species)
您确定 n_distinct 是您想要的吗?在鸢尾花数据集的情况下,有三个物种 - setosa、versicolor、virginica。因此,每个物种都是 1/3 独特的物种。 Iris 数据集是平衡的,因为每个物种有 50 个,因此每个物种代表数据集的 1/3,但更普遍的情况并非如此。
具有数据屏蔽功能的函数将为您覆盖不平衡的数据集:
library(dplyr)
my_func <- function(df, var, percent){
df %>%
count({{var}}) %>%
mutate(percent = 100 * n/sum(n))
}
my_func(iris, Species, percent)
iris %>%
my_func(Species, percent) #or with pipe
另一种可能的解决方案,它使用 deparse(substitute(...))
将函数参数的名称作为字符串获取:
library(tidyverse)
f <- function(df, group_var, summary_var)
{
group_var <- deparse(substitute(group_var))
summary_var <- deparse(substitute(summary_var))
df %>%
group_by(!!sym(group_var)) %>%
summarise(!!str_c("num_", summary_var) := n_distinct(summary_var)) %>%
mutate(!!str_c("per_", summary_var) := 100 * !!sym(str_c("num_", summary_var)) / sum(!!sym(str_c("num_", summary_var))))
}
f(iris, Species, Species)
#> # A tibble: 3 × 3
#> Species num_Species per_Species
#> <fct> <int> <dbl>
#> 1 setosa 1 33.3
#> 2 versicolor 1 33.3
#> 3 virginica 1 33.3