我已经看过几篇关于如何使用dplyr
函数编写自己的函数的帖子。例如,您可以看到如何在this post中使用group_by (regroup)
和summarise
。我认为看看我是否可以使用主要dplyr
函数编写函数会很有趣。我希望我们可以进一步了解如何使用dplyr
函数编写函数。
数据
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)
目标
我想在函数中编写以下过程。
foo %>%
mutate(new = ifelse(value > 60, 1, 0)) %>%
filter(id %in% c("a", "b", "d")) %>%
group_by(country) %>%
summarize(whatever = sum(value))
TRY
### 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
您可能会发现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)
鉴于第一个实验成功,我很难理解为什么第二个实验失败了。在第二个实验中可能有一些事情要做有人有想法吗?感谢您抽出宝贵时间。
答案 0 :(得分:7)
关闭issue 352后,我安装了 dplyr 0.3 和 lazyeval ,看看如何在其他功能中使用dplyr
功能。在阅读vignette on non-standard evaluation后,看起来{strong> lazyeval 中的interp
与以_
结尾的新功能相结合是一种选择。注意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)
首先是函数外的代码/结果:
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
然后将上述过程转换为函数:
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)))
}
这会产生预期的效果。
myFun(foo, "value", "id", "country")
Source: local data frame [2 x 2]
country whatever
1 France 213.0009
2 UK 207.8331
对于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")
答案 1 :(得分:3)
实际上,您的实验不起作用,您将遇到所有这些问题的范围问题。看起来它们正在工作,因为您已在全局环境中定义了向量country
,id
和value
,但未删除它们。因此,当您调用函数时,他们正在使用全局环境中的向量。
要显示此信息,请在调用函数之前删除这些向量:
创建向量和data.frame:
library(dplyr)
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)
定义你的第一个功能:
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 208.1008
2 UK 192.4287
现在删除向量并调用你的函数(现在它不起作用,因为它无法找到向量):
rm(country, id, value)
myFun(foo, value, id, "country")
mutate_impl(.data,named_dots(...),environment())出错:
对象&#39;价值&#39;找不到
这就解释了为什么你的安排例子在其他人做的时候不起作用。您的第二个实验调用的向量是全局环境中的向量country
,它有10个元素。但是函数排列只期望6个元素,这是过滤矢量的结果。
您有不同的策略可以让您的功能发挥作用。例如,请查看t his answer by G. Grothendieck以获得有关如何操作的一些见解。或者等一下,正如哈德利指出的那样,programming in dplyr is a future feature coming soon.