4

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

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))
4

2 回答 2

5

当您使用 时summariseplyr在检查函数 in 之前似乎“看不到”在全局环境中声明的函数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>

environments如果您有兴趣进一步阅读/探索它,这里有一个来自 Hadley 的很棒的 wiki

于 2013-03-02T10:42:15.790 回答
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
于 2013-03-02T10:37:36.650 回答