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

を使用するsummariseと、plyrの関数をチェックする前に、グローバル環境で宣言された関数が「見えない」ようですbase:

pryrこれは、Hadley の便利なパッケージを使用して確認できます。次のコマンドでインストールできます。

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>

基本的に、それはあなたの 機能を読んだり、知ったり、見たりしませんmode2 つの選択肢があります。最初は@AnandaMahtoが提案したもので、私も同じことをして、それに固執するようアドバイスします。もう 1 つの選択肢は、使用せずに使用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>

environmentsHadleyのすばらしい wiki

于 2013-03-02T10:42:15.790 に答える
2

あなたの例では、既存の関数名をほぼ排他的に使用しています: levelscat、およびmode. 一般に、これは大きな問題にはなりません。たとえば、data.frame "df" を呼び出しても、R のdf()機能は壊れません。しかし、ほとんどの場合、よりあいまいで混乱を招くコードになり、この場合、物事が「壊れる」ことになります。アルンの答えは、その理由を示す素晴らしい仕事をしています。

「モード」関数の名前を変更することで、問題を簡単に解決できます。以下の例では、名前を変更するだけでなく、少し単純化しています。期待どおりに動作します。

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 に答える