【问题标题】:Why is R dplyr::mutate inconsistent with custom functions为什么 R dplyr::mutate 与自定义函数不一致
【发布时间】:2018-04-22 15:21:54
【问题描述】:

这个问题是“为什么”,而不是如何。在下面的代码中,我试图理解为什么dplyr::mutate 使用整个向量而不是其他自定义函数 (g()) 来评估一个自定义函数 (f())。 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))

对于所有三列,asqfoutgout,在 y2y3 中按行进行评估,结果相同。但是,y1$fout 对于所有三行都是 3640.889,这是评估 sum(rnorm(100, c(0, 10, 100))) 的结果。所以函数f() 正在评估每一行的整个向量。

在其他地方mutate/transform in R dplyr (Pass custom function) 提出了一个密切相关的问题,但没有解释“为什么”。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    sin^ 是矢量化的,因此它们本身对每个单独的值进行操作,而不是对整个值向量进行操作。 f 未矢量化。但是您可以使用f = Vectorize(f),它也会对每个单独的值进行操作。

    y1 <- mutate(df, asq=a^2, fout=f(a), gout=g(a))
    y1
    
        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
    
    f = Vectorize(f)
    
    y1a <- mutate(df, asq=a^2, fout=f(a), gout=g(a))
    y1a
    
        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
    

    有关矢量化hereherehere 的一些附加信息。

    【讨论】:

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

    我们可以使用map循环遍历'a'的每个元素并应用函数f

    library(tidyverse)
    df %>%
        mutate(asq = a^2, fout = map_dbl(a, f), gout = g(a)) 
    #    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
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-05
    • 1970-01-01
    • 1970-01-01
    • 2020-04-04
    • 1970-01-01
    相关资源
    最近更新 更多