主要的dplyr函数在函数中

jaz*_*rro 3 r dplyr

我已经看过几篇关于如何用dplyr函数编写自己的函数的帖子.例如,您可以在此帖子中看到如何使用group_by (regroup)和.我认为看看我是否可以使用主要功能编写函数会很有趣.我希望我们可以进一步了解如何使用函数编写函数.summarisedplyrdplyr

数据

country <- rep(c("UK", "France"), each = 5)
id <- rep(letters[1:5], times = 2)
value <- runif(10, 50, 100)
foo <- data.frame(country, id, value, stringsAsFactors = FALSE)
Run Code Online (Sandbox Code Playgroud)

目标

我想在函数中编写以下过程.

foo %>%
    mutate(new = ifelse(value > 60, 1, 0)) %>%
    filter(id %in% c("a", "b", "d")) %>%
    group_by(country) %>%
    summarize(whatever = sum(value))
Run Code Online (Sandbox Code Playgroud)

尝试

### Here is a function which does the same process

myFun <- function(x, ana, bob, cathy) x %>%
    mutate(new = ifelse(ana > 60, 1, 0)) %>%
    filter(bob %in% c("a", "b", "d")) %>%
    regroup(as.list(cathy)) %>%
    summarize(whatever = sum(ana))

myFun(foo, value, id, "country")

Source: local data frame [2 x 2]

  country whatever
1  France 233.1384
2      UK 245.5400
Run Code Online (Sandbox Code Playgroud)

你可能会意识到那arrange()不存在.这是我正在努力的那个.这是两个观察结果.第一个实验是成功的.这些国家的顺序从英国 - 法国变为法国 - 英国.但第二个实验并不成功.

### Experiment 1: This works for arrange()

myFun <- function(x, ana) x %>%
         arrange(ana)

myFun(foo, country)

   country id    value
1   France  a 90.12723
2   France  b 86.64229
3   France  c 74.93320
4   France  d 80.69495
5   France  e 72.60077
6       UK  a 84.28033
7       UK  b 67.01209
8       UK  c 94.24756
9       UK  d 79.49848
10      UK  e 63.51265


### Experiment2: This was not successful.

myFun <- function(x, ana, bob) x %>%
         filter(ana %in% c("a", "b", "d")) %>%
         arrange(bob)

myFun(foo, id, country)

Error: incorrect size (10), expecting :6

### This works, by the way.
foo %>%
filter(id %in% c("a", "b", "d")) %>%
arrange(country)
Run Code Online (Sandbox Code Playgroud)

鉴于第一个实验是成功的,我很难理解为什么第二个实验失败了.在第二个实验中可能有一些事情要做有人有想法吗?感谢您抽出宝贵时间.

aos*_*ith 7

一旦问题352关闭,我就安装了dplyr 0.3lazyeval,看看它如何在另一个函数中使用函数.在阅读了关于非标准评估小插图之后,从lazyeval到结尾的新功能看起来就是一个选项.现在请注意替换.dplyrinterp_group_by_regroup

set.seed(16)
foo = data.frame(country = rep(c("UK", "France"), each = 5), 
               id = rep(letters[1:5], times = 2), 
               value = runif(10, 50, 100), stringsAsFactors = FALSE)
Run Code Online (Sandbox Code Playgroud)

首先是函数外的代码/结果:

library(lazyeval)
library(dplyr)

foo %>%
    mutate(new = ifelse(value > 60, 1, 0)) %>%
    filter(id %in% c("a", "b", "d")) %>%
    group_by(country) %>%
    summarize(whatever = sum(value))

Source: local data frame [2 x 2]

  country whatever
1  France 213.0009
2      UK 207.8331
Run Code Online (Sandbox Code Playgroud)

然后将上面的过程变成一个函数:

myFun = function(x, ana, bob, cathy) {
    x %>%
        mutate_(new = interp(~ifelse(var > 60 , 1, 0), var = as.name(ana))) %>%
        filter_(interp(~var %in% c("a", "b", "d"), var = as.name(bob))) %>%
        group_by_(cathy) %>%
        summarize_(whatever = interp(~sum(var), var = as.name(ana)))
}
Run Code Online (Sandbox Code Playgroud)

这给出了期望的结果.

myFun(foo, "value", "id", "country")
Source: local data frame [2 x 2]

  country whatever
1  France 213.0009
2      UK 207.8331
Run Code Online (Sandbox Code Playgroud)

对于你的第二个问题arrange,我试过了

myfun2 = function(x, ana, bob) x%>%
    filter_(interp(~var %in% c("a", "b", "d"), var = as.name(ana))) %>%
    arrange_(as.name(bob))

myfun2(foo, "id", "country")
Run Code Online (Sandbox Code Playgroud)