如何使用 do() 从 plyr 复制结果
How to use do() to replicate a result from plyr
这是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 之前,这些部分并没有分开。
即,如果我在 browser()
停止 fn2 时键入 dim(x)
,我会在 plyr
示例中得到 1000 2
,在 dplyr
示例中得到 7000 2
。
有没有什么方法可以像我一直使用的 plyr
一样,将 dplyr
用于用户定义的函数?
谢谢,
乔恩
我认为这可行....
您应该检查结果是否符合要求...
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(.)
这是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 之前,这些部分并没有分开。
即,如果我在 browser()
停止 fn2 时键入 dim(x)
,我会在 plyr
示例中得到 1000 2
,在 dplyr
示例中得到 7000 2
。
有没有什么方法可以像我一直使用的 plyr
一样,将 dplyr
用于用户定义的函数?
谢谢,
乔恩
我认为这可行....
您应该检查结果是否符合要求...
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(.)