【问题标题】:Calculating most frequent level by category with plyr使用 plyr 按类别计算最频繁的级别
【发布时间】:2013-03-02 10:12:47
【问题描述】:

我想用 plyr 使用下面的代码按类别计算最常见的因子水平。数据框b 显示了请求的结果。为什么c$mlevels 的值只有“numeric”?

require(plyr)
set.seed(0)
a <- data.frame(cat=round(runif(100, 1, 3)),
                levels=factor(round(runif(100, 1, 10))))
mode <- function(x) names(table(x))[which.max(table(x))]
b <- data.frame(cat=1:3,
                mlevels=c(mode(a$levels[a$cat==1]),
                       mode(a$levels[a$cat==2]),
                       mode(a$levels[a$cat==3])))
c <- ddply(a, .(cat), summarise,
           mlevels=mode(levels))

【问题讨论】:

    标签: r plyr


    【解决方案1】:

    当您使用summarise 时,plyr 在检查base 中的函数之前似乎“看不到”全局环境中声明的函数:

    我们可以使用 Hadley 方便的 pryr 包检查这一点。您可以通过以下命令安装它:

    library(devtools)
    install_github("pryr")
    
    
    require(pryr)
    require(plyr)
    c <- ddply(a, .(cat), summarise, print(where("mode")))
    # <environment: namespace:base>
    # <environment: namespace:base>
    # <environment: namespace:base>
    

    基本上,它不读取/知道/查看您的 mode 函数。有两个选项。第一个是@AnandaMahto 的建议,我也会这样做,并建议你坚持下去。另一种选择是不使用 summarise 并使用 function(.) 调用它,以便“看到”全局环境中的 mode 函数。

    c <- ddply(a, .(cat), function(x) mode(x$levels))
    #   cat V1
    # 1   1  6
    # 2   2  5
    # 3   3  9
    

    为什么会这样?

    c <- ddply(a, .(cat), function(x) print(where("mode")))
    # <environment: R_GlobalEnv>
    # <environment: R_GlobalEnv>
    # <environment: R_GlobalEnv>
    

    因为正如您在上面看到的,它会读取您位于 global environment 中的函数。

    > mode # your function
    # function(x)
    #     names(table(x))[which.max(table(x))]
    > environment(mode) # where it sits
    # <environment: R_GlobalEnv>
    

    相对于:

    > base::mode # base's mode function
    # function (x) 
    # {
    #     some lines of code to compute mode
    # }
    # <bytecode: 0x7fa2f2bff878>
    # <environment: namespace:base>
    

    Here's an awesome wiki environments 来自 Hadley,如果您有兴趣进一步阅读/探索它。

    【讨论】:

    • +1,这比我的答案好多。我懒得去探索 plyr 在哪里寻找“模式”,所以我只是重命名并简化了它。
    • 感谢您的回答,它正在工作。我试着总结一下:模式已经存在于全局环境中,因此 plyr 正在使用我提供的模式功能。
    • @user2126360, mode 存在于base
    • 不。您的功能存在于全球环境中。但是summarise“看到”了一个不同的mode,默认情况下是base。这就是为什么@AnandaMahto 在他的编辑中解释说,使用 R 中已经使用的所有默认名称是不明智的,因为您的代码更有可能被破坏。
    • 另见here函数:ddply(a, .(cat), here(summarise), mlevels=mode(levels))。文档中的解释应该会有所帮助。
    【解决方案2】:

    您在示例中几乎只使用了现有函数名称:levelscatmode。通常,这不会造成太大问题——例如,调用 data.frame "df" 不会破坏 R 的 df() 函数。但它几乎总是会导致代码更加模棱两可或令人困惑,而在 这种 的情况下,它会让事情“崩溃”。 Arun 的回答很好地说明了原因。

    您可以通过重命名“模式”函数轻松解决问题。在下面的示例中,除了重命名它之外,我还对其进行了一些简化,并且它可以按您的预期工作。

    Mode <- function(x) names(which.max(table(x)))
    ddply(a, .(cat), summarise,
          mlevels=Mode(levels))
    #   cat mlevels
    # 1   1       6
    # 2   2       5
    # 3   3       9
    

    当然,有一个非常麻烦的解决方法:使用get 并指定搜索函数的位置。

    > mode <- function(x) names(table(x))[which.max(table(x))]
    > ddply(a, .(cat), summarise, mlevels = get("mode", ".GlobalEnv")(levels))
      cat mlevels
    1   1       6
    2   2       5
    3   3       9
    

    【讨论】:

      猜你喜欢
      • 2018-03-13
      • 1970-01-01
      • 2013-08-28
      • 1970-01-01
      • 1970-01-01
      • 2011-01-27
      • 1970-01-01
      • 1970-01-01
      • 2022-01-06
      相关资源
      最近更新 更多