使用 dplyr 编程:间接控制按哪些变量分组
Programming with dplyr: indirectly control by which variables to group by
我想编写一个简单的函数 f(grouping)
来汇总以下数据:
d0 <- data.frame(
V1 = rep(1:5, times = 2),
V2 = rep(2:6, times = 2),
V3 = rep(11:15, times = 2),
V4 = rep(12:16, times = 2),
X = 1:10
)
我希望用户能够在两种分组之间进行选择:按 V1
或按 V2
,因为用户可以写 f(grouping = V1)
或 f(grouping = V2)
.但是,我希望它是这样的,如果 grouping = V1
,它按 V1
和 V3
分组。如果 grouping = V2
,则按 V2
和 V4
分组。请注意,由于 V3
和 V4
最初的名称不直观,因此不应将它们用作函数调用的参数。
f(V1)
应该产生:
# A tibble: 5 x 3
# Groups: V1 [5]
V1 V3 X
<int> <int> <int>
1 1 11 7
2 2 12 9
3 3 13 11
4 4 14 13
5 5 15 15
和f(V2)
:
# A tibble: 5 x 3
# Groups: V2 [5]
V2 V4 X
<int> <int> <int>
1 2 12 7
2 3 13 9
3 4 14 11
4 5 15 13
5 6 16 15
我们使用 if/else
创建一个条件,以根据输入 grouping
的值连接 'V3' 或 'V4'。在函数内部,将不带引号的分组值转换为符号(ensym
),再转换为字符串(as_string
),然后使用if/else
拼接组,将更新后的组('grp') 在 across
和 summarise
中 'X'
f1 <- function(data, grouping) {
grp <- rlang::as_string(ensym(grouping))
grp <- c(grp, if(grp == 'V1') 'V3' else 'V4')
data %>%
group_by(across(all_of(grp))) %>%
summarise(X = sum(X), .groups = 'drop')
}
f1(d0, V1)
f1(d0, V2)
我想编写一个简单的函数 f(grouping)
来汇总以下数据:
d0 <- data.frame(
V1 = rep(1:5, times = 2),
V2 = rep(2:6, times = 2),
V3 = rep(11:15, times = 2),
V4 = rep(12:16, times = 2),
X = 1:10
)
我希望用户能够在两种分组之间进行选择:按 V1
或按 V2
,因为用户可以写 f(grouping = V1)
或 f(grouping = V2)
.但是,我希望它是这样的,如果 grouping = V1
,它按 V1
和 V3
分组。如果 grouping = V2
,则按 V2
和 V4
分组。请注意,由于 V3
和 V4
最初的名称不直观,因此不应将它们用作函数调用的参数。
f(V1)
应该产生:
# A tibble: 5 x 3
# Groups: V1 [5]
V1 V3 X
<int> <int> <int>
1 1 11 7
2 2 12 9
3 3 13 11
4 4 14 13
5 5 15 15
和f(V2)
:
# A tibble: 5 x 3
# Groups: V2 [5]
V2 V4 X
<int> <int> <int>
1 2 12 7
2 3 13 9
3 4 14 11
4 5 15 13
5 6 16 15
我们使用 if/else
创建一个条件,以根据输入 grouping
的值连接 'V3' 或 'V4'。在函数内部,将不带引号的分组值转换为符号(ensym
),再转换为字符串(as_string
),然后使用if/else
拼接组,将更新后的组('grp') 在 across
和 summarise
中 'X'
f1 <- function(data, grouping) {
grp <- rlang::as_string(ensym(grouping))
grp <- c(grp, if(grp == 'V1') 'V3' else 'V4')
data %>%
group_by(across(all_of(grp))) %>%
summarise(X = sum(X), .groups = 'drop')
}
f1(d0, V1)
f1(d0, V2)