例如,假设您有一个函数应用了一些 DPLYR 函数,但您不能期望传递给该函数的数据集具有相同的列名。
对于我的意思的一个简化示例,假设您有一个数据框 arizona.trees
:
arizona.trees
group arizona.redwoods arizona.oaks
A 23 11
A 24 12
B 9 8
B 10 7
C 88 22
和另一个非常相似的数据框,california.trees
:
california.trees
group california.redwoods california.oaks
A 25 50
A 11 33
B 90 5
B 77 3
C 90 35
并且您想实现一个函数,该函数返回给定类型树的给定组(A、B、... Z)的平均值,该函数适用于这两个数据框。
foo <- function(dataset, group1, group2, tree.type) {
column.name <- colnames(dataset[2])
result <- filter(dataset, group %in% c(group1, group2) %>%
select(group, contains(tree.type)) %>%
group_by(group) %>%
summarize("mean" = mean(column.name))
return(result)
}
调用 foo(california.trees, A, B, redwoods)
所需的输出将是:
result
mean
A 18
B 83.5
出于某种原因,执行foo()
之类的操作似乎行不通。这可能是由于数据框索引存在一些错误 - 该函数似乎认为我正在尝试获取 column.name
字符串的平均值,而不是检索该列并将该列传递给 均值()
。我不确定如何避免这种情况。存在隐式传递修改后的数据帧的问题,管道运算符无法直接引用可能导致该问题的问题。
这是为什么?是否有一些可行的替代实现方案?
最佳答案
我们可以使用 dplyr
开发版本(即将发布 0.6.0
)中基于 quosure
的解决方案
foo <- function(dataset, group1, group2, tree.type){
group1 <- quo_name(enquo(group1))
group2 <- quo_name(enquo(group2))
colN <- rlang::parse_quosure(names(dataset)[2])
tree.type <- quo_name(enquo(tree.type))
dataset %>%
filter(group %in% c(group1, group2)) %>%
select(group, contains(tree.type)) %>%
group_by(group) %>%
summarise(mean = mean(UQ(colN)))
}
foo(california.trees, A, B, redwoods)
# A tibble: 2 × 2
# group mean
# <chr> <dbl>
#1 A 18.0
#2 B 83.5
foo(arizona.trees, A, B, redwoods)
# A tibble: 2 × 2
# group mean
# <chr> <dbl>
#1 A 23.5
#2 B 9.5
enquo
接受输入参数并将其转换为quosure
,使用quo_name
,将其转换为字符串以与一起使用%in%
,第二列名称使用 parse_quosure
从字符串转换为 quosure
,然后不加引号(UQ
或 !!
) 在 summarise
注意:这是基于OP关于选择第二列的功能
上述解决方案基于根据位置选择列(根据 OP 的代码),它可能不适用于其他列。因此,我们可以匹配“tree.type”并根据它获得列的“平均值”
foo1 <- function(dataset, group1, group2, tree.type){
group1 <- quo_name(enquo(group1))
group2 <- quo_name(enquo(group2))
tree.type <- quo_name(enquo(tree.type))
dataset %>%
filter(group %in% c(group1, group2)) %>%
select(group, contains(tree.type)) %>%
group_by(group) %>%
summarise_at(vars(contains(tree.type)), funs(mean = mean(.)))
}
可以针对两个数据集中的不同列测试函数
foo1(arizona.trees, A, B, oaks)
# A tibble: 2 × 2
# group mean
# <chr> <dbl>
#1 A 11.5
#2 B 7.5
foo1(arizona.trees, A, B, redwood)
# A tibble: 2 × 2
# group mean
# <chr> <dbl>
#1 A 23.5
#2 B 9.5
foo1(california.trees, A, B, redwood)
# A tibble: 2 × 2
# group mean
# <chr> <dbl>
#1 A 18.0
#2 B 83.5
foo1(california.trees, A, B, oaks)
# A tibble: 2 × 2
# group mean
# <chr> <dbl>
#1 A 41.5
#2 B 4.0
arizona.trees <- structure(list(group = c("A", "A", "B", "B", "C"),
arizona.redwoods = c(23L,
24L, 9L, 10L, 88L), arizona.oaks = c(11L, 12L, 8L, 7L, 22L)),
.Names = c("group",
"arizona.redwoods", "arizona.oaks"), class = "data.frame",
row.names = c(NA, -5L))
california.trees <- structure(list(group = c("A", "A", "B", "B", "C"),
california.redwoods = c(25L,
11L, 90L, 77L, 90L), california.oaks = c(50L, 33L, 5L, 3L, 35L
)), .Names = c("group", "california.redwoods", "california.oaks"
), class = "data.frame", row.names = c(NA, -5L))
https://stackoverflow.com/questions/43641851/