[英]How do I create a function to mutate new columns with a variable name and "_pct"?
以mtcars
為例。 我想寫一個 function 來創建一個count
和pct
列,如下所示 -
library(tidyverse)
mtcars %>%
group_by(cyl) %>%
summarise(count = n()) %>%
ungroup() %>%
mutate(cyl_pct = count/sum(count))
這將產生 output -
# A tibble: 3 x 3
cyl count mpg_pct
<dbl> <int> <dbl>
1 4 11 0.344
2 6 7 0.219
3 8 14 0.438
但是,我想創建一個 function ,我可以在其中將group_by
列指定為任何列,而mutate
列將命名為groub_by
中指定的列名和一個_pct
。 因此,如果我想使用disp
, disp
將是我的group_by
變量,並且 function 將改變disp_pct
列。
類似於 akrun 的答案,但使用{{
而不是!!
:
foo = function(data, col) {
data %>%
group_by({{col}}) %>%
summarize(count = n()) %>%
ungroup %>%
mutate(
"{{col}}_pct" := count / sum(count)
)
}
foo(mtcars, cyl)
# `summarise()` ungrouping output (override with `.groups` argument)
# # A tibble: 3 x 3
# cyl count cyl_pct
# <dbl> <int> <dbl>
# 1 4 11 0.344
# 2 6 7 0.219
# 3 8 14 0.438
假設輸入未加引號,使用ensym
轉換為符號,在group_by
中評估 ( !!
),同時將符號轉換為字符串 ( as_string
) 並粘貼新列名的前綴 '_pct'。 在mutate
中,我們可以使用:=
和!!
從創建的 object 中分配列名('colnm')
library(stringr)
library(dplyr)
f1 <- function(dat, grp) {
grp <- ensym(grp)
colnm <- str_c(rlang::as_string(grp), '_pct')
dat %>%
group_by(!!grp) %>%
summarise(count = n(), .groups = 'drop') %>%
mutate(!! colnm := count/sum(count))
}
-測試
f1(mtcars, cyl)
# A tibble: 3 x 3
# cyl count cyl_pct
# <dbl> <int> <dbl>
#1 4 11 0.344
#2 6 7 0.219
#3 8 14 0.438
這可能與我親愛的朋友@akrun 發布的沒有什么不同。 但是,在我的版本中,我使用enquo
function 而不是ensym
。 兩者之間實際上存在細微差別,我想您可能有興趣知道:
nse-defuse
的文檔, ensym
返回一個原始表達式,而enquo
返回一個“quosure”,它實際上是一個“包含表達式和環境的包裝器”。 所以我們需要一個額外的步驟來訪問由enquo
的 quosure 表達式。get_expr
來達到我們的目的。 因此,這只是編寫此 function 的另一個版本,我認為未來閱讀這篇文章的人可能會對它感興趣。library(dplyr)
library(rlang)
fn <- function(data, Var) {
Var <- enquo(Var)
colnm <- paste(get_expr(Var), "pct", sep = "_")
data %>%
group_by(!!Var) %>%
summarise(count = n()) %>%
ungroup() %>%
mutate(!! colnm := count/sum(count))
}
fn(mtcars, cyl)
# A tibble: 3 x 3
cyl count cyl_pct
<dbl> <int> <dbl>
1 4 11 0.344
2 6 7 0.219
3 8 14 0.438
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.