R函数:使用参数作为字符变量和列名
R function: using argument as a character variable and column name
我有一些这种格式的数据:
#> # A tibble: 3 × 5
#> item cost blue pink black
#> <int> <int> <int> <int> <int>
#> 1 1 4 1 0 1
#> 2 2 10 1 0 1
#> 3 3 3 0 1 1
我想要的输出是颜色列的相对频率。项目可以有不止一种颜色,因此相对频率总和不必为 1。
#> color rel_freq
#> <int> <int>
#> 1 blue 0.66
#> 2 pink 0.33
#> 2 black 1.00
我可以为一种颜色手动完成,比如蓝色:
library(tidyverse)
df <- tibble::tribble(
~item, ~cost, ~blue, ~pink, ~black,
1L, 4L, 1L, 0L, 1L,
2L, 10L, 1L, 0L, 1L,
3L, 3L, 0L, 1L, 1L
)
df %>%
group_by(blue) %>%
summarise(count = n()) %>%
mutate(rel_freq = (count/sum(count)*100) ) %>%
filter(blue==1) %>%
mutate(color = deparse(substitute(blue))) %>%
select(-blue, -count) %>%
select(color, everything())
这给出了
#> color rel_freq
#> <chr> <dbl>
#> 1 blue 66.7
但是当我把它放入一个函数中时,我不知道如何传入一个参数,以便它可以被视为一个列(使用“curly-curly”表示法)和一个字符变量(这就是我所坚持的)。
calc_rel_freq <- function(input_color){
df %>%
group_by({{input_color}}) %>%
summarise(count = n()) %>%
mutate(rel_freq = (count/sum(count)*100) ) %>%
filter({{input_color}}==1) %>%
mutate(color = deparse(substitute({{input_color}}))) %>% # This is where I'm stuck.
select(-{{input_color}}, -count) %>%
select(color, everything())
}
calc_rel_freq(blue)
我的最终目标是能够使用这样的函数:
input_colors <- c("blue", "pink", "black")
map(input_colors, calc_relative_freq)
数据输入代码如下:
library(tidyverse)
df <- tibble::tribble(
~item, ~cost, ~blue, ~pink, ~black,
1L, 4L, 1L, 0L, 1L,
2L, 10L, 1L, 0L, 1L,
3L, 3L, 0L, 1L, 1L
)
df
由于您想要的输出是相对频率,您可以更直接地使用
df %>%
select(-cost) %>%
pivot_longer(blue:black) %>%
group_by(name) %>%
summarize(rel_freq=mean(value))
# name rel_freq
# <chr> <dbl>
# 1 black 1
# 2 blue 0.667
# 3 pink 0.333
如果你真的只想要一个,你可以在最后 filter()
。
我们可以将 dplyr 与 across
一起使用。对于所有答案,如果需要,我们可以轻松 pivot_longer
输出。
library(dplyr)
df %>% summarise(across(blue:black, mean))
# A tibble: 1 × 3
blue pink black
<dbl> <dbl> <dbl>
1 0.667 0.333 1
和all_of
across
也可以通过 all_of
选择助手处理所选列的名称向量:
library(dplyr)
input_colors <- c("blue", "pink", "black")
df %>% summarise(across(all_of(input_colors), mean))
有sym
和双刘海(!!
)
如果我们真的想使用非标准评估将字符元素用作dplyr函数内的列选择,我们可以转换为符号(sym
)并评估(!!
),用rlang
包:
library(dplyr)
library(purrr)
library(rlang)
map_dfc(input_colors, ~df %>% summarise(across(!!(sym(.x)), mean)))
# A tibble: 1 × 3
blue pink black
<dbl> <dbl> <dbl>
1 0.667 0.333 1
作为替代方案,我们可以先创建一个符号列表
my_symbols<-input_colors %>% map(sym)
然后使用循环 across
:
map_dfc(my_symbols, ~ df %>% summarise(across(.x, mean)))
在用户自定义函数中使用双大括号({{}}
)
尽管有警告消息,但它工作得很好:
calc_rel_freq<-function(df, variable){
df %>% summarise(across({{variable}}, mean))
}
rel_freq(df, input_colors)
Note: Using an external vector in selections is ambiguous.
ℹ Use `all_of(input_colors)` instead of `input_colors` to silence this message.
ℹ See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.
This message is displayed once per session.
# A tibble: 1 × 3
blue pink black
<dbl> <dbl> <dbl>
1 0.667 0.333 1
我有一些这种格式的数据:
#> # A tibble: 3 × 5
#> item cost blue pink black
#> <int> <int> <int> <int> <int>
#> 1 1 4 1 0 1
#> 2 2 10 1 0 1
#> 3 3 3 0 1 1
我想要的输出是颜色列的相对频率。项目可以有不止一种颜色,因此相对频率总和不必为 1。
#> color rel_freq
#> <int> <int>
#> 1 blue 0.66
#> 2 pink 0.33
#> 2 black 1.00
我可以为一种颜色手动完成,比如蓝色:
library(tidyverse)
df <- tibble::tribble(
~item, ~cost, ~blue, ~pink, ~black,
1L, 4L, 1L, 0L, 1L,
2L, 10L, 1L, 0L, 1L,
3L, 3L, 0L, 1L, 1L
)
df %>%
group_by(blue) %>%
summarise(count = n()) %>%
mutate(rel_freq = (count/sum(count)*100) ) %>%
filter(blue==1) %>%
mutate(color = deparse(substitute(blue))) %>%
select(-blue, -count) %>%
select(color, everything())
这给出了
#> color rel_freq
#> <chr> <dbl>
#> 1 blue 66.7
但是当我把它放入一个函数中时,我不知道如何传入一个参数,以便它可以被视为一个列(使用“curly-curly”表示法)和一个字符变量(这就是我所坚持的)。
calc_rel_freq <- function(input_color){
df %>%
group_by({{input_color}}) %>%
summarise(count = n()) %>%
mutate(rel_freq = (count/sum(count)*100) ) %>%
filter({{input_color}}==1) %>%
mutate(color = deparse(substitute({{input_color}}))) %>% # This is where I'm stuck.
select(-{{input_color}}, -count) %>%
select(color, everything())
}
calc_rel_freq(blue)
我的最终目标是能够使用这样的函数:
input_colors <- c("blue", "pink", "black")
map(input_colors, calc_relative_freq)
数据输入代码如下:
library(tidyverse)
df <- tibble::tribble(
~item, ~cost, ~blue, ~pink, ~black,
1L, 4L, 1L, 0L, 1L,
2L, 10L, 1L, 0L, 1L,
3L, 3L, 0L, 1L, 1L
)
df
由于您想要的输出是相对频率,您可以更直接地使用
df %>%
select(-cost) %>%
pivot_longer(blue:black) %>%
group_by(name) %>%
summarize(rel_freq=mean(value))
# name rel_freq
# <chr> <dbl>
# 1 black 1
# 2 blue 0.667
# 3 pink 0.333
如果你真的只想要一个,你可以在最后 filter()
。
我们可以将 dplyr 与 across
一起使用。对于所有答案,如果需要,我们可以轻松 pivot_longer
输出。
library(dplyr)
df %>% summarise(across(blue:black, mean))
# A tibble: 1 × 3
blue pink black
<dbl> <dbl> <dbl>
1 0.667 0.333 1
和all_of
across
也可以通过 all_of
选择助手处理所选列的名称向量:
library(dplyr)
input_colors <- c("blue", "pink", "black")
df %>% summarise(across(all_of(input_colors), mean))
有sym
和双刘海(!!
)
如果我们真的想使用非标准评估将字符元素用作dplyr函数内的列选择,我们可以转换为符号(sym
)并评估(!!
),用rlang
包:
library(dplyr)
library(purrr)
library(rlang)
map_dfc(input_colors, ~df %>% summarise(across(!!(sym(.x)), mean)))
# A tibble: 1 × 3
blue pink black
<dbl> <dbl> <dbl>
1 0.667 0.333 1
作为替代方案,我们可以先创建一个符号列表
my_symbols<-input_colors %>% map(sym)
然后使用循环 across
:
map_dfc(my_symbols, ~ df %>% summarise(across(.x, mean)))
在用户自定义函数中使用双大括号({{}}
)
尽管有警告消息,但它工作得很好:
calc_rel_freq<-function(df, variable){
df %>% summarise(across({{variable}}, mean))
}
rel_freq(df, input_colors)
Note: Using an external vector in selections is ambiguous.
ℹ Use `all_of(input_colors)` instead of `input_colors` to silence this message.
ℹ See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.
This message is displayed once per session.
# A tibble: 1 × 3
blue pink black
<dbl> <dbl> <dbl>
1 0.667 0.333 1