传递列名的变量?

时间:2017-04-26 18:25:15

标签: r variables dplyr

例如,假设您有一个应用了某些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字符串的均值,而不是检索列并将列传递给mean()。我不确定如何避免这种情况。存在修改的数据帧的隐式传递问题,该问题无法直接引用可能导致问题的管道操作符。

这是为什么?是否有一些可行的替代实现?

1 个答案:

答案 0 :(得分:4)

我们可以使用quosure的devel版本中基于dplyr的解决方案(即将发布0.6.0

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%一起使用,第二列名称将被转换使用quosure从字符串parse_quosure开始,然后在UQ

内对其进行评分(!!summarise)进行评估

注意:这是基于OP关于选择第二列的功能

上述解决方案基于根据位置选择列(根据OP的代码),它可能不适用于其他列。所以,我们可以匹配&#39; tree.type&#39;得到“意思是”&#39;基于那个

的列
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))