1. ホーム
  2. r

[解決済み] グループ化関数(tapply、by、aggregate)と*applyファミリ

2022-03-22 07:30:50

質問

R で何か "map"py をしたいとき、私はいつも apply のファミリーです。

しかし、私はこの2つの違いをよく理解していませんでした。 sapply , lapply 入力やグループ化された入力に関数を適用したり、出力がどのように見えるか、あるいは入力が何になり得るか、などです。したがって、私はしばしば、欲しいものが得られるまでこれらすべてを調べます。

どなたか、どのタイミングでどれをどう使うか、説明していただけませんか?

私の現在の(おそらく不正確/不完全な)理解は...

  1. sapply(vec, f) 入力はベクトル,出力はベクトル/マトリックス,要素は if(vec[i]) の場合、行列ができます。 f は複数要素の出力を持ちます。

  2. lapply(vec, f) と同じです。 sapply しかし、出力はリストですか?

  3. apply(matrix, 1/2, f) 入力は行列,出力はベクトルで,その要素は i はf(行列の行/列i)
  4. tapply(vector, grouping, f) 出力は行列/配列であり,行列/配列の各要素は f をグループ分けして g のベクトル、および g は、行/列の名前にプッシュされます。
  5. by(dataframe, grouping, f) : let g はグループ化されます。 f グループ/データフレームの各カラムに、グループ化された値と f を各列に配置する。
  6. aggregate(matrix, grouping, f) と同様です。 by しかし、出力をきれいに印刷する代わりに、集約はデータフレームにすべてを貼り付けます。

横から質問です。私はまだplyrやreshapeを学んでいません。 plyr または reshape は、これらをすべて完全に置き換えるのですか?

どのように解決するのですか?

Rには多くの*apply関数があり、ヘルプファイル(例:Abstract)で適切に説明されています。 ?apply ). しかし、その数は非常に多く、初心者はどれが自分の状況に適しているのか判断するのが難しく、また、それらをすべて覚えることすら難しいかもしれません。一般的な感覚として「*apply関数をここで使うべきだな」というのはわかるかもしれませんが、最初にそれらをすべて整理しておくのは大変なことです。

他の回答でも指摘されていますが、*applyファミリーの機能の多くは、非常に人気の高い*apply.comでカバーされています。 plyr パッケージがありますが、基本的な関数は依然として便利であり、知る価値があります。

この回答は、ある種の 道しるべ を使用することで、特定の問題に対する正しい*適用関数を導き出すことができます。注:これは ではなく Rのドキュメントをそのまま流用したり、置き換えたりすることを意図しています。この回答は、どの*apply関数が自分の状況に合っているかを決めるのに役立ち、その後、さらに研究するのはあなた次第であることを望みます。例外として、性能の違いについては触れません。

  • 適用 - 行または列に関数を適用したい場合。 の行列(および高次元相似行列)。最初に行列に変換されるため、一般にデータフレームには適していません。

     # Two dimensional matrix
     M <- matrix(seq(1,16), 4, 4)
    
     # apply min to rows
     apply(M, 1, min)
     [1] 1 2 3 4
    
     # apply max to columns
     apply(M, 2, max)
     [1]  4  8 12 16
    
     # 3 dimensional array
     M <- array( seq(32), dim = c(4,4,2))
    
     # Apply sum across each M[*, , ] - i.e Sum across 2nd and 3rd dimension
     apply(M, 1, sum)
     # Result is one-dimensional
     [1] 120 128 136 144
    
     # Apply sum across each M[*, *, ] - i.e Sum across 3rd dimension
     apply(M, c(1,2), sum)
     # Result is two-dimensional
          [,1] [,2] [,3] [,4]
     [1,]   18   26   34   42
     [2,]   20   28   36   44
     [3,]   22   30   38   46
     [4,]   24   32   40   48
    
    

    2 次元行列の行/列の平均や和が必要な場合は、必ず は、高度に最適化された、電光石火の速さの colMeans , rowMeans , colSums , rowSums .

  • ラップリ - の各要素に関数を適用したい場合。 のリストを順番に取得し、リストを返します。

    これは、他の多くの*apply関数の主力となるものです。この関数は を使用することができます。 lapply の下にあります。

     x <- list(a = 1, b = 1:3, c = 10:100) 
     lapply(x, FUN = length) 
     $a 
     [1] 1
     $b 
     [1] 3
     $c 
     [1] 91
     lapply(x, FUN = sum) 
     $a 
     [1] 1
     $b 
     [1] 6
     $c 
     [1] 5005
    
    
  • サップル - の各要素に関数を適用したい場合。 を順番に表示させたいが ベクトル を、リストではなくバックで返します。

    もし、あなたが unlist(lapply(...)) を考えてみてください。 sapply .

     x <- list(a = 1, b = 1:3, c = 10:100)
     # Compare with above; a named vector, not a list 
     sapply(x, FUN = length)  
     a  b  c   
     1  3 91
    
     sapply(x, FUN = sum)   
     a    b    c    
     1    6 5005 
    
    

    をより高度に使用する場合 sapply を強制しようとします。 を多次元配列に変換することができます。例えば、この関数が同じ長さのベクトルを返すとします。 sapply は、それらを行列の列として使用します。

     sapply(1:5,function(x) rnorm(3,x))
    
    

    我々の関数が2次元の行列を返す場合。 sapply は基本的に同じことを行い、返された各行列を1つの長いベクトルとして扱います。

     sapply(1:5,function(x) matrix(x,2,2))
    
    

    を指定しない限り simplify = "array" この場合、個々の行列を使用して多次元配列が構築されます。

     sapply(1:5,function(x) matrix(x,2,2), simplify = "array")
    
    

    これらの動作は、もちろん、関数が同じ長さまたは次元のベクトルまたは行列を返すことを条件としています。

  • バップリ - を使いたいとき sapply が必要かもしれません。 を使用することで、より高速化することができます。 型の安全性を高めたい .

    について vapply は、基本的にRにどのようなものの例を示すものです。 これは、返される関数を強制的に変更する時間を節約することができます。 の値が1つのアトミックベクターに収まるようにします。

     x <- list(a = 1, b = 1:3, c = 10:100)
     #Note that since the advantage here is mainly speed, this
     # example is only for illustration. We're telling R that
     # everything returned by length() should be an integer of 
     # length 1. 
     vapply(x, FUN = length, FUN.VALUE = 0L) 
     a  b  c  
     1  3 91
    
    
  • マッピィ - 複数のデータ構造(例. ベクトルやリストなど)があり,ある関数をその1番目の要素に適用したい場合 それぞれの2番目の要素,というように,結果を強制することができます。 のようにベクトル/配列に変換します。 sapply .

    これは多変量解析で、関数は必ず の複数の引数があります。

     #Sums the 1st elements, the 2nd elements, etc. 
     mapply(sum, 1:5, 1:5, 1:5) 
     [1]  3  6  9 12 15
     #To do rep(1,4), rep(2,3), etc.
     mapply(rep, 1:4, 4:1)   
     [[1]]
     [1] 1 1 1 1
    
     [[2]]
     [1] 2 2 2
    
     [[3]]
     [1] 3 3
    
     [[4]]
     [1] 4
    
    
  • 地図 - のラッパーです。 mapplySIMPLIFY = FALSE であるため、リストを返すことが保証されています。

     Map(sum, 1:5, 1:5, 1:5)
     [[1]]
     [1] 3
    
     [[2]]
     [1] 6
    
     [[3]]
     [1] 9
    
     [[4]]
     [1] 12
    
     [[5]]
     [1] 15
    
    
  • 汲み上げる - の各要素に関数を適用したい場合。 ネストされたリスト 構造体を再帰的に作成します。

    どのように珍しいかを説明するために rapply は、この回答を投稿した当初は忘れていましたよ。もちろん、多くの人が使っているとは思いますが、YMMVです。 rapply は、適用するユーザー定義関数で説明するのが一番わかりやすいと思います。

     # Append ! to string, otherwise increment
     myFun <- function(x){
         if(is.character(x)){
           return(paste(x,"!",sep=""))
         }
         else{
           return(x + 1)
         }
     }
    
     #A nested list structure
     l <- list(a = list(a1 = "Boo", b1 = 2, c1 = "Eeek"), 
               b = 3, c = "Yikes", 
               d = list(a2 = 1, b2 = list(a3 = "Hey", b3 = 5)))
    
    
     # Result is named vector, coerced to character          
     rapply(l, myFun)
    
     # Result is a nested list like l, with values altered
     rapply(l, myFun, how="replace")
    
    
  • タップリ - に関数を適用したい場合 サブセット の ベクトルによって定義され、その部分集合は他のベクトル、通常は 係数です。

    applyファミリーの黒い羊、みたいなもの。ヘルプファイルでは というフレーズがあります。 紛らわしい しかし、実際には は非常にシンプルです。

    ベクトルです。

     x <- 1:20
    
    

    グループを定義する因子(同じ長さ!)。

     y <- factor(rep(letters[1:5], each = 4))
    
    

    の値を足し合わせます。 x で定義された各サブグループ内で y :

     tapply(x, y, sum)  
      a  b  c  d  e  
     10 26 42 58 74 
    
    

    より複雑な例として、サブグループが定義されている場合にも対応可能です。 いくつかの要因のリストのユニークな組み合わせによって。 tapply は の分割・適用・結合関数に似ています。 Rで一般的な( aggregate , by , ave , ddply それゆえ 黒子的な存在。