繁体   English   中英

调整功能以使用dplyr / magrittr

[英]Adjust function to work with dplyr/magrittr

我有:

df <- data_frame(
  a = 1:2, 
  b = list(1:10, 4:40)
)

foo <- function(x) mean(unlist(x))

以下按预期工作:

df$b %>% foo

但是,为了使df %>% foo(b)起作用,我无法弄清楚需要对foo进行哪些修改。

您可以将...参数直接传递给summarise_atvars帮助程序,例如

foo <- function(.tbl, ...){
    summarise_at(.tbl, 
                 vars(...), 
                 funs(mean(unlist(.))))
}

它适用于单个变量,列表列是否:

df %>% foo(b)
## # A tibble: 1 × 1
##          b
##      <dbl>
## 1 18.48936

或多个:

df %>% foo(a, b)
## # A tibble: 1 × 2
##       a        b
##   <dbl>    <dbl>
## 1   1.5 18.48936

要进一步了解NSE,请查看lazyeval ,这是dplyr用来实现其NSE的包。

另请注意,dplyr的SE / NSE系统刚刚在开发版本中重建(尚未在CRAN上重建,尚未记录)。


加分点:在R基础上做到这一切!

foo <- function(.tbl, ...){
    # collect dots as character vector
    cols <- as.character(substitute(list(...))[-1])
    cls <- class(.tbl)

    # handle grouped tibbles properly
    if('grouped_df' %in% cls){
        cls <- cls[which(cls != 'grouped_df')]    # drop grouping
        res <- aggregate(.tbl[cols], 
                         .tbl[attr(.tbl, 'vars')], 
                         FUN = function(x){mean(unlist(x))})
    } else {
        res <- as.data.frame(lapply(.tbl[cols], function(x){mean(unlist(x))}))
    }

    class(res) <- cls    # keep class (tibble, etc.)
    res
}

它适用于列表列,组和多个列或组,保持类但丢弃分组:

df %>% foo(a, b)
## # A tibble: 1 × 2
##       a        b
##   <dbl>    <dbl>
## 1   1.5 18.48936

df %>% group_by(a) %>% foo(b)
## # A tibble: 2 × 2
##       a     b
##   <int> <dbl>
## 1     1   5.5
## 2     2  22.0

mtcars %>% foo(mpg, hp)
##        mpg       hp
## 1 20.09062 146.6875

mtcars %>% group_by(cyl, am) %>% foo(hp, mpg)
## # A tibble: 6 × 4
##     cyl    am        hp      mpg
##   <dbl> <dbl>     <dbl>    <dbl>
## 1     4     0  84.66667 22.90000
## 2     6     0 115.25000 19.12500
## 3     8     0 194.16667 15.05000
## 4     4     1  81.87500 28.07500
## 5     6     1 131.66667 20.56667
## 6     8     1 299.50000 15.40000

你可以这样得到结果:

library(dplyr)
library(purrr)
df %>% 
    mutate_(mn=~map_dbl(b, mean), size=~map_dbl(b, length)) %>%
    summarize_(m=~weighted.mean(mn, size))
#  m
#   <dbl>
# 1 18.49

或者以这种方式定义foo

foo2 <- function(d, col) {
    col_name <- as.character(substitute(col))
    mean(unlist(d[[col_name]]))
}
df %>% foo2(b)
[1] 18.49

您可以使用以下内容更新函数:

foo <- function(df, x) {
  x <- df[ deparse(substitute(x))] 
  mean(unlist(x)) }

df %>% foo(b)
[1] 18.48936

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM