为什么R dplyr :: mutate与自定义函数不一致

Rob*_*ald 4 r dplyr

这个问题是"为什么",而不是如何.在下面的代码中,我试图理解为什么用整个向量dplyr::mutate计算一个自定义函数(f())而不用另一个自定义函数(g()).究竟在mutate做什么?

set.seed(1);sum(rnorm(100, c(0, 10, 100)))
f=function(m) {
    set.seed(1)
    sum(rnorm(100, mean=m))
}
g <- function(m) sin(m)
df <- data.frame(a=c(0, 10, 100))
y1 <- mutate(df, asq=a^2, fout=f(a), gout=g(a))
y2 <- rowwise(df) %>%
    mutate(asq=a^2, fout=f(a), gout=g(a))
y3 <- group_by(df, a) %>%
    summarize(asq=a^2, fout=f(a), gout=g(a))
Run Code Online (Sandbox Code Playgroud)

对于所有三列,asq,fout,和gout,评价是横行中y2y3,结果是相同的.但是,y1$fout对于所有三行,这是3640.889,这是评估的结果sum(rnorm(100, c(0, 10, 100))).因此该函数f()正在评估每一行的整个向量.

一个密切相关的问题已经在R dplyr(Pass自定义函数)中的其他位置进行mutate/transform,但是没有解释"为什么".

eip*_*i10 6

sin并且^是矢量化的,因此它们本身对每个单独的值进行操作,而不是对整个值向量进行操作.f没有矢量化.但你可以这样做f = Vectorize(f),它也将对每个单独的价值进行操作.

y1 <- mutate(df, asq=a^2, fout=f(a), gout=g(a))
y1
Run Code Online (Sandbox Code Playgroud)
    a   asq     fout       gout
1   0     0 3640.889  0.0000000
2  10   100 3640.889 -0.5440211
3 100 10000 3640.889 -0.5063656
Run Code Online (Sandbox Code Playgroud)
f = Vectorize(f)

y1a <- mutate(df, asq=a^2, fout=f(a), gout=g(a))
y1a
Run Code Online (Sandbox Code Playgroud)
    a   asq        fout       gout
1   0     0    10.88874  0.0000000
2  10   100  1010.88874 -0.5440211
3 100 10000 10010.88874 -0.5063656
Run Code Online (Sandbox Code Playgroud)

关于矢量化的一些额外信息,这里,这里这里.

  • 这是一个很好的答案,谢谢。矢量化的链接很重要。我的心智模型是 mutate 隐式地在做一个循环,但如果我理解正确的话,它不是,它正在传递一个向量。这是有道理的,并解释了我的示例中的不同结果。 (2认同)