R rlang:处理 NULL 参数?
R rlang: handle NULL arguments?
我想将默认值为 NULL
的可选参数用于 dplyr
函数(比如 count()
)。如果我将标准过程与 !!enquo()
一起使用,我会收到错误消息:错误:列 NULL
未知 。
有趣的是,rlang/tidyverse
允许缺失值,所以如果 NULL 可以转换为缺失值,但看起来很脏(特别是如果我想在之后使用 facet_grid
,那接受NULL 但不丢失)。
library(tidyverse)
df <- tibble(a = sample(LETTERS[1:2], 100, replace = TRUE),
b = sample(LETTERS[3:4], 100, replace = TRUE),
value = rnorm(100,5,1))
f2 <- function(df, group_var1=a, group_var2=NULL, group_var3) {
res <- df %>%
count({{group_var1}}, {{group_var2}}, {{group_var3}})
print(res)
ggplot(aes(x=a, y=n), data = res)+
geom_col() +
facet_grid(row= enquo(group_var2))
}
f2(df, group_var1 = a, group_var2=b)
#> # A tibble: 4 x 3
#> a b n
#> <chr> <chr> <int>
#> 1 A C 26
#> 2 A D 29
#> 3 B C 16
#> 4 B D 29
f2(df, group_var1 = a)
#> Error: Column `NULL` is unknown
由 reprex package (v0.3.0)
于 2019-08-04 创建
group_by
和 count
都不会接受 NULL
值。因此,您必须首先使用 enquos
创建一个 quosures 对象,并对 NULL
值进行子集化。由于 count
只是 tally
和 group_by
的包装器,我们可以使用 group_by
.[=28 的 group_by_at
范围版本手动分组和计数=]
f2 <- function(df, group_var1=a, group_var2=NULL, group_var3) {
grps <- enquos(a = group_var1, b = group_var2, c = group_var3, .ignore_empty = "all")
# this removes the NULL values
grps <- grps[map_lgl(grps, ~ !quo_is_null(.))]
res <- df %>%
group_by_at(grps) %>%
tally() %>%
ungroup()
print(res)
}
这很好地创建了 res
数据框:
> f2(df, group_var1 = a, group_var2=b)
# A tibble: 4 x 3
a b n
<chr> <chr> <int>
1 A C 20
2 A D 30
3 B C 22
4 B D 28
> f2(df, group_var1 = a)
# A tibble: 2 x 2
a n
<chr> <int>
1 A 50
2 B 50
然而,我们在尝试创建剧情时又遇到了问题。 enquo
创建了一个带引号的对象,所以 NULL
变成了 "NULL"
(更准确地说是 `NULL`),所以 ggplot 不知道如何处理它。所以我认为条件语句是可行的方法:
f2 <- function(df, group_var1=a, group_var2=NULL, group_var3) {
grps <- enquos(a = group_var1, b = group_var2, c = group_var3, .ignore_empty = "all")
grps <- grps[map_lgl(grps, ~ !quo_is_null(.))]
res <- df %>%
group_by_at(grps) %>%
tally() %>%
ungroup()
print(res)
if (quo_is_null(enquo(group_var2))) {
ggplot(aes(x=a, y=n), data = res)+
geom_col()
} else(
ggplot(aes(x=a, y=n), data = res)+
geom_col() +
facet_grid(row= enquo(group_var2))
)
}
根据 Matifo 的评论更新:
library(tidyverse)
library(rlang)
df <- tibble(a = sample(LETTERS[1:2], 100, replace = TRUE),
b = sample(LETTERS[3:4], 100, replace = TRUE),
value = rnorm(100,5,1))
f2 <- function(df, group_var1=a, group_var2=NULL, group_var3) {
grps <- enquos(a = group_var1, b = group_var2, c = group_var3, .ignore_empty = "all")
grps <- grps[map_lgl(grps, ~ !quo_is_null(.))]
res <- df %>%
count(!!!grps)
print(res)
ggplot(aes(x=a, y=n), data = res)+
geom_col() +
facet_grid(row= enquos(group_var2))
}
f2(df, group_var1 = a, group_var2=b)
#> # A tibble: 4 x 3
#> a b n
#> <chr> <chr> <int>
#> 1 A C 29
#> 2 A D 33
#> 3 B C 18
#> 4 B D 20
f2(df, group_var1 = a)
#> # A tibble: 2 x 2
#> a n
#> <chr> <int>
#> 1 A 62
#> 2 B 38
我想将默认值为 NULL
的可选参数用于 dplyr
函数(比如 count()
)。如果我将标准过程与 !!enquo()
一起使用,我会收到错误消息:错误:列 NULL
未知 。
有趣的是,rlang/tidyverse
允许缺失值,所以如果 NULL 可以转换为缺失值,但看起来很脏(特别是如果我想在之后使用 facet_grid
,那接受NULL 但不丢失)。
library(tidyverse)
df <- tibble(a = sample(LETTERS[1:2], 100, replace = TRUE),
b = sample(LETTERS[3:4], 100, replace = TRUE),
value = rnorm(100,5,1))
f2 <- function(df, group_var1=a, group_var2=NULL, group_var3) {
res <- df %>%
count({{group_var1}}, {{group_var2}}, {{group_var3}})
print(res)
ggplot(aes(x=a, y=n), data = res)+
geom_col() +
facet_grid(row= enquo(group_var2))
}
f2(df, group_var1 = a, group_var2=b)
#> # A tibble: 4 x 3
#> a b n
#> <chr> <chr> <int>
#> 1 A C 26
#> 2 A D 29
#> 3 B C 16
#> 4 B D 29
f2(df, group_var1 = a)
#> Error: Column `NULL` is unknown
由 reprex package (v0.3.0)
于 2019-08-04 创建group_by
和 count
都不会接受 NULL
值。因此,您必须首先使用 enquos
创建一个 quosures 对象,并对 NULL
值进行子集化。由于 count
只是 tally
和 group_by
的包装器,我们可以使用 group_by
.[=28 的 group_by_at
范围版本手动分组和计数=]
f2 <- function(df, group_var1=a, group_var2=NULL, group_var3) {
grps <- enquos(a = group_var1, b = group_var2, c = group_var3, .ignore_empty = "all")
# this removes the NULL values
grps <- grps[map_lgl(grps, ~ !quo_is_null(.))]
res <- df %>%
group_by_at(grps) %>%
tally() %>%
ungroup()
print(res)
}
这很好地创建了 res
数据框:
> f2(df, group_var1 = a, group_var2=b)
# A tibble: 4 x 3
a b n
<chr> <chr> <int>
1 A C 20
2 A D 30
3 B C 22
4 B D 28
> f2(df, group_var1 = a)
# A tibble: 2 x 2
a n
<chr> <int>
1 A 50
2 B 50
然而,我们在尝试创建剧情时又遇到了问题。 enquo
创建了一个带引号的对象,所以 NULL
变成了 "NULL"
(更准确地说是 `NULL`),所以 ggplot 不知道如何处理它。所以我认为条件语句是可行的方法:
f2 <- function(df, group_var1=a, group_var2=NULL, group_var3) {
grps <- enquos(a = group_var1, b = group_var2, c = group_var3, .ignore_empty = "all")
grps <- grps[map_lgl(grps, ~ !quo_is_null(.))]
res <- df %>%
group_by_at(grps) %>%
tally() %>%
ungroup()
print(res)
if (quo_is_null(enquo(group_var2))) {
ggplot(aes(x=a, y=n), data = res)+
geom_col()
} else(
ggplot(aes(x=a, y=n), data = res)+
geom_col() +
facet_grid(row= enquo(group_var2))
)
}
根据 Matifo 的评论更新:
library(tidyverse)
library(rlang)
df <- tibble(a = sample(LETTERS[1:2], 100, replace = TRUE),
b = sample(LETTERS[3:4], 100, replace = TRUE),
value = rnorm(100,5,1))
f2 <- function(df, group_var1=a, group_var2=NULL, group_var3) {
grps <- enquos(a = group_var1, b = group_var2, c = group_var3, .ignore_empty = "all")
grps <- grps[map_lgl(grps, ~ !quo_is_null(.))]
res <- df %>%
count(!!!grps)
print(res)
ggplot(aes(x=a, y=n), data = res)+
geom_col() +
facet_grid(row= enquos(group_var2))
}
f2(df, group_var1 = a, group_var2=b)
#> # A tibble: 4 x 3
#> a b n
#> <chr> <chr> <int>
#> 1 A C 29
#> 2 A D 33
#> 3 B C 18
#> 4 B D 20
f2(df, group_var1 = a)
#> # A tibble: 2 x 2
#> a n
#> <chr> <int>
#> 1 A 62
#> 2 B 38