gpt4 book ai didi

r - 使用具有自定义功能的ddply + mutate吗?

转载 作者:行者123 更新时间:2023-12-01 21:21:12 25 4
gpt4 key购买 nike

我经常使用ddply,但从历史上讲,它是summarize(有时是mutate),只有基本功能(例如mean()var1 - var2等)。我在一个数据集中尝试应用自定义,参与程度更高的功能,并开始尝试研究如何用ddply做到这一点。我有一个成功的解决方案,但是我不明白为什么它会像这样,而对于更多的“正常”功能却如此。

相关的

  • Custom Function not recognized by ddply {plyr}...
  • How do I pass variables to a custom function in ddply?
  • r-help: [R] Correct use of ddply with own function(我最终基于此解决方案)

  • 这是一个示例数据集:
    library(plyr)
    df <- data.frame(id = rep(letters[1:3], each = 3),
    value = 1:9)

    通常,我会像这样使用 ddply:
    df_ply_1 <- ddply(df, .(id), mutate, mean = mean(value))

    我对此的可视化是 ddply根据 df的组合组合将 id拆分为“小型”数据帧,然后通过对 mean()中存在的列名称调用 df来添加新列。因此,我尝试实现一个功能扩展了这个想法:
    # actually, my logical extension of the above was to use:
    # ddply(..., mean = function(value) { mean(value) })
    df_ply_2 <- ddply(df, .(id), mutate,
    mean = function(df) { mean(df$value) })

    Error: attempt to replicate an object of type 'closure'

    关于自定义函数的所有帮助都没有应用 mutate,但是这似乎前后矛盾,或者至少让我讨厌,因为与我实现的解决方案类似:
    df_mean <- function(df) {
    temp <- data.frame(mean = rep(mean(df$value), nrow(df)))
    temp
    }

    df_ply_3 <- df
    df_ply_3$mean <- ddply(df, .(id), df_mean)$mean

    内联,看来我必须这样做:
    df_ply_4 <- df
    df_ply_4$mean <- ddply(df, .(id), function(x) {
    temp <- data.frame(mean = rep(mean(x$value), length(x$value)))
    temp})$mean

    为什么不能将 mutate与自定义函数一起使用?仅仅是“内置”函数返回 ddply可以处理的某种类,而必须踢出完整的 data.frame然后仅调出我关心的列吗?

    感谢您帮助我“获得”它!

    @Gregor回答后更新

    很棒的答案,我想我明白了。确实,我对 mutatesummarize的含义感到困惑...认为它们是 ddply的参数,涉及如何处理结果与实际上是函数本身。因此,感谢您的深刻见解。

    另外,它确实有助于理解没有 mutate/summarize,我需要返回 data.frame,这就是我必须对返回的 cbind中的列名进行 df的原因。

    最后,如果我确实使用 mutate,那么现在可以返回向量结果并获得正确的结果将非常有帮助。因此,我可以做到这一点,在阅读您的回答后,我现在已经明白了:
    # I also caught that the code above doesn't do the right thing
    # and recycles the single value returned by mean() vs. repeating it like
    # I expected. Now that I know it's taking a vector, I know I need to return
    # a vector the same length as my mini df
    custom_mean <- function(x) {
    rep(mean(x), length(x))
    }

    df_ply_5 <- ddply(df, .(id), mutate,
    mean = custom_mean(value))

    再次感谢您的深入解答!

    根据@Gregor的最新评论更新

    嗯出于对 rep(mean(x), length(x))结果的观察,我使用了 df_ply_3(我第一次发表这篇文章时,并没有仔细观察它,我只是发现它并没有给我带来错误!):
    df_mean <- function(x) {
    data.frame(mean = mean(x$value))
    }

    df_ply_3 <- df
    df_ply_3$mean <- ddply(df, .(id), df_mean)$mean

    df_ply_3
    id value mean
    1 a 1 2
    2 a 2 5
    3 a 3 8
    4 b 4 2
    5 b 5 5
    6 b 6 8
    7 c 7 2
    8 c 8 5
    9 c 9 8

    因此,我基于3个 id变量重复3次这一事实,认为我的代码实际上是一次意外。因此,实际返回等于 summarize(每个 id值一行),并被回收。如果我像这样更新我的数据框,则对该理论的测试似乎是正确的:
    df <- data.frame(id = c(rep(letters[1:3], each = 3), "d"),
    value = 1:10)

    尝试将 df_ply_3方法与 df_mean()结合使用时出现错误:
    Error in `$<-.data.frame`(`*tmp*`, "mean", value = c(2, 5, 8, 10)) : 
    replacement has 4 rows, data has 10

    因此,传递给 df_mean的mini df返回 df,其中 meanvalue向量(返回一个值)取平均值的结果。因此,我的输出只是一个包含三个值的 data.frame,每个 id组一个。我在想 mutate方式“记住”它已传递一个小型数据帧,然后重复单个输出以匹配其长度?

    无论如何,感谢您对 df_ply_5的评论;的确,如果我删除 rep()位并仅返回 mean(x),那么效果很好!

    最佳答案

    你基本上是对的。 ddply确实根据石斑鱼将您的数据分解为微型数据帧,并对每个片段都应用了一个函数。

    使用ddply,所有工作都通过数据帧完成,因此.fun参数必须以一个(小型)数据帧作为输入,并返回一个数据帧作为输出。
    mutatesummarize是适合此要求的函数(它们获取和返回数据帧)。您可以查看他们的个人帮助页面,也可以在ddply之外的数据框中运行它们,例如

    mutate(mtcars, mean.mpg = mean(mpg))
    summarize(mtcars, mean.mpg = mean(mpg))

    如果您不使用 mutatesummarize,也就是说,您 使用自定义函数,那么您的函数还需要采用一个(小型)数据帧作为参数,并返回一个数据帧。

    如果 使用mutatesummarize,则传递给 ddply的任何其他函数都不会被 ddply使用,它们只会传递给 mutatesummarize使用。 mutatesummarize使用的函数作用于数据的列,而不作用于整个data.frame。这就是为什么
    ddply(mtcars, "cyl", mutate, mean.mpg = mean(mpg))

    请注意,我们没有将 mutate传递给函数。我们不说 ddply(mtcars, "cyl", mutate, mean)。我们必须告诉它要表达什么意思。在 ?mutate中, ...的描述是“给新列定义的命名参数”,与函数无关。 ( mean()与任何“自定义函数”真的不同吗?)

    因此,它不适用于匿名函数-或根本不起作用。传递一个表情!您可以预先定义一个自定义函数。
    custom_function <- function(x) {mean(x + runif(length(x))}
    ddply(mtcars, "cyl", mutate, jittered.mean.mpg = custom_function(mpg))
    ddply(mtcars, "cyl", summarize, jittered.mean.mpg = custom_function(mpg))

    这很好地扩展了,您可以具有接受多个参数的函数,并且可以为它们提供不同的列作为参数,但是,如果您使用 mutatesummarize,则必须给其他函数提供参数;您不只是传递函数。

    您似乎想要传递 ddply一个已经“知道”平均值的函数。为此,我认为您不需要使用 mutatesummarize,但是您可以破解自己的版本。对于类似 summarize的行为,返回带有单个值的data.frame,对于类似于 mutate的行为,返回原始data.frame,并在其上加上额外的值 cbind
    mean.mpg.mutate = function(df) {
    cbind.data.frame(df, mean.mpg = mean(df$mpg))
    }

    mean.mpg.summarize = function(df) {
    data.frame(mean.mpg = mean(df$mpg))
    }

    ddply(mtcars, "cyl", mean.mpg.mutate)
    ddply(mtcars, "cyl", mean.mpg.summarize)

    tl; dr

    Why can't I use mutate with a custom function? Is it just that "built-in" functions return some sort of class that ddply can deal with vs. having to kick out a full data.frame and then call out only the column I care about?



    恰恰相反! mutatesummarize将数据帧作为输入,并踢出数据帧作为返回。但是mutt和总结 就是您要传递给ddply的函数,而不是指其他任何东西。

    Mutate和summary是便利功能,您将在 ddply的99%的时间中使用它们。

    如果您不使用mutate/summaryize,则您的函数需要获取并返回一个数据帧。

    如果您确实使用了mutate/summitize,那么您就不会传递它们的功能,而是传递可以用您的(小型)数据帧求值的表达式。如果是变异的,则返回值应该是要附加到数据的向量(必要时回收)。如果是汇总,则返回值应为单个值。您没有传递像 mean这样的函数;您传递一个表达式,例如 mean(mpg)

    dplyr呢?

    这是在 dplyr还是一件大事之前写的。 dplyr消除了此过程中的许多困惑,因为它实际上将 ddply的嵌套替换为 mutatesummarize作为带有顺序函数 group_by后跟 mutatesummarize的参数的嵌套。我的答案的 dplyr版本是
    library(dplyr)
    group_by(mtcars, cyl) %>%
    mutate(mean.mpg = mean(mpg))

    将新的列创建直接传递给 mutate(或 summarize)后,对于哪个函数执行什么操作就不会感到困惑。

    关于r - 使用具有自定义功能的ddply + mutate吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26935150/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com