以下是plyr
中的一段代码。我通过分组变量A分割数据帧dta,然后将用户定义的函数fn应用于每个部分:
require(plyr)
dta <- data.frame(
A=rep(LETTERS[1:7], each=1000),
B=runif(7000)
)
fn <- function(x){
y <- x
multiplier <- ifelse(
x$A[1] %in% c("A", "D", "E"),
3, 2
)
to_multiply <- y$B > 0.3
y$B[to_multiply] <- y$B[to_multiply] *multiplier
return(y)
}
dta_der <- ddply(dta, .(A), fn)
这正如我所料。 (注意,功能本身并不重要。这只是一个例子。)
现在,我希望使用dplyr
require(dplyr)
dta <- data.frame(
A=rep(LETTERS[1:7], each=1000),
B=runif(7000)
)
fn <- function(x){
y <- x
multiplier <- ifelse(
x$A[1] %in% c("A", "D", "E"),
3, 2
)
to_multiply <- y$B > 0.3
y$B[to_multiply] <- y$B[to_multiply] *multiplier
return(y)
}
dta %>%
group_by(A) %>%
do(fn)
然而,它产生Error: Results are not data frames at positions: 1, 2, 3, 4, 5, 6, 7
而不是预期的结果。
更糟糕的是,plyr
我可以为fn()
fn2 <- function(x){
browser()
out <- NULL
}
这对于能够看到传递给fn
的每个'piece'的内容非常有用,以确保它具有预期的内容和结构,并相应地帮助开发功能。使用dplyr
时,此骨架结构会在一开始就产生错误。
如果不是使用do,而是将分组的tbl_df对象直接传递给fn,不会产生错误,但是在传递给fn之前,这些片段不会分开。
即如果我在dim(x)
暂停fn2时输入browser()
,我会在1000 2
示例中获得plyr
,在7000 2
示例中获得dplyr
。
有没有办法使用dplyr
作为用户定义的函数,因为我一直在使用plyr
?
谢谢,
乔恩
答案 0 :(得分:5)
我觉得这很有效......
你应该检查结果是否符合要求......
dta %>%
group_by(A) %>%
do(fn(.))
# A B
#1 A 0.22276975
#2 A 0.01183619
#3 A 1.84315247
#4 A 0.19809142
#5 A 0.08114770
#6 A 1.48606944
#7 A 0.84864389
#8 A 0.60060566
#9 A 0.25362720
#10 A 1.68528202
顺便说一句,如果您不想使用do
,可以使用%$%
magrittr
管道运算符
dta %>%
group_by(A) %$%
fn(.)