R 为列名传递变量?
例如,假设您有一个应用了一些DPLYR函数的函数,但您不能期望传递给该函数的数据集具有相同的列名 对于我的意思的简化示例,假设您有一个数据帧,R 为列名传递变量?,r,variables,dplyr,R,Variables,Dplyr,例如,假设您有一个应用了一些DPLYR函数的函数,但您不能期望传递给该函数的数据集具有相同的列名 对于我的意思的简化示例,假设您有一个数据帧,arizona.trees: arizona.trees group arizona.redwoods arizona.oaks A 23 11 A 24 12 B 9 8 B 10
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()
这样的操作似乎不起作用。这可能是由于数据帧索引中出现了一些错误-函数似乎认为我试图获取列.name
字符串的平均值,而不是检索列并将列传递给mean()
。我不知道如何避免这种情况。有一个问题是隐式传递修改后的数据帧,该数据帧不能直接用管道操作符引用,这可能是导致该问题的原因
为什么会这样?是否有其他可行的实现方案?我们可以使用
dplyr
的devel版本中基于quosure
的解决方案(即将发布0.6.0
)
可以针对两个数据集中的不同列测试该函数
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
foo1(亚利桑那州,树木,A,B,橡树)
#一个tibble:2×2
#群平均
#
#1 A 11.5
#2 B 7.5
foo1(亚利桑那州,树木,A,B,红木)
#一个tibble:2×2
#群平均
#
#1 A 23.5
#2 B 9.5
foo1(加州树木,A,B,红木)
#一个tibble:2×2
#群平均
#
#1A 18.0
#2 B 83.5
foo1(加州,树木,A,B,橡树)
#一个tibble:2×2
#群平均
#
#1 A 41.5
#2B4.0
数据
arizona.trees您必须阅读dplyr()的“非标准评估”(nse)小插曲,并注意此方法将在下一个dplyr版本中更改(),感谢您的快速回复!如果不使用devel版本的dplyr
,就没有办法做到这一点吗?@user3450277 devel版本将很快发布为0.6.0。预计在4月,5月进入CRAN。否则,您可以使用摘要
etc函数,但它们很快就会被弃用。如果您打算进行生产级编码,那么最好是长期编码。感谢您非常详细的回复!如果您以前没有使用过开发版本,那么安装它很容易(就像回滚到当前版本一样):install.packages(“devtools”)#如果您没有使用过devtools::install\u github(“tidyverse/dplyr”)
回滚只是一个普通的install.packages(“dplyr”)
call。dev版本中的Tidyeval功能是解决问题的关键:
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
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))