グループ化関数(tapply、by、aggregate)および* applyファミリー

1069
grautur 2010-08-18 08:31.

Rで何か「マップ」を実行したいときはいつでも、私は通常、applyファミリ内の関数を使用しようとします。

ただし、{、、など}が入力/グループ化された入力に関数を適用する方法、出力がどのように見えるか、または入力がどのようになるかなどsapply、それらの違いを完全に理解したことはありませんlapply。私が欲しいものを手に入れるまで、それらすべてを通り抜けるだけです。

誰かがいつどのように使用するかを説明できますか?

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

  1. sapply(vec, f):入力はベクトルです。出力はベクトル/行列です。ここで、要素if(vec[i])です。f複数要素の出力がある場合は、行列が得られます。

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

  3. apply(matrix, 1/2, f):入力は行列です。出力はベクトルです。ここで、要素iはf(行列の行/列)です。
  4. tapply(vector, grouping, f):出力は行列/配列です。ここで、行列/配列の要素は、ベクトルのfグループ化gでの値でありg、行/列名にプッシュされます。
  5. by(dataframe, grouping, f)gグループ化しましょう。fグループ/データフレームの各列に適用されます。f各列のグループ化と値をきれいに出力します。
  6. aggregate(matrix, grouping, f):に似てbyいますが、出力をきれいに出力する代わりに、aggregateはすべてをデータフレームに貼り付けます。

副次的な質問:私はまだプライヤーや形状変更を学んでいません-これらすべてを完全に置き換えるのでしょうplyrreshape

10 answers

1355
joran 2011-08-22 12:50.

Rには、ヘルプファイル(例?apply)に適切に記述されている多くの* apply関数があります。ただし、それらは十分にあるため、useRを開始すると、状況に適したものを決定したり、すべてを覚えたりするのが難しい場合があります。「ここでは* apply関数を使うべきだ」という一般的な感覚があるかもしれませんが、最初はすべてをまっすぐに保つのは難しいかもしれません。

* applyファミリーの機能の多くが非常に人気のあるplyrパッケージでカバーされているという事実(他の回答に記載されています)にもかかわらず、基本関数は引き続き有用であり、知っておく価値があります。

この回答は、新しいuseRの一種の道標として機能し、特定の問題に対して正しい* apply関数に誘導することを目的としています。これは、単にRドキュメントを逆流または置換することを意図したものではないことに注意してください。この回答が、どの*適用関数が状況に適しているかを判断するのに役立ち、それをさらに調査するのはあなた次第です。1つの例外を除いて、パフォーマンスの違いは対処されません。

  • 適用-行列(および高次元の類似体)の行または列に関数を適用する場合。データフレームは最初にマトリックスに強制変換されるため、通常はお勧めできません。

    # 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
    

    あなたは、2D行列の行/列手段または合計をしたい場合は、高度に最適化され、雷、迅速に調査するようにしてくださいcolMeansrowMeanscolSumsrowSums

  • lapply -あなたは順番にリストの各要素に関数を適用し、リストの背中を取得したいときに。

    これは、他の多くの* 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
    
  • sapply -あなたは順番にリストの各要素に関数を適用したいのですが、あなたが欲しいベクトルバックではなく、リストを。

    入力していることに気付いた場合は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基本的に同じことを行い、返された各行列を単一の長いベクトルとして扱います。

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

    を指定しない限り、指定しないsimplify = "array"場合は、個々の行列を使用して多次元配列を作成します。

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

    もちろん、これらの動作のそれぞれは、同じ長さまたは次元のベクトルまたは行列を返す関数に依存します。

  • vapply -あなたが使用したい場合はsapplyおそらくあなたのコードのうち、いくつかのより多くの速度を絞る必要があります。

    の場合vapply、基本的にRに関数が返すものの例を示します。これにより、戻り値を単一のアトミックベクトルに強制的に強制する時間を節約できます。

    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
    
  • mapply -のようにベクトル/配列に結果を強制するなど、あなたはいくつかのデータ構造(例えばベクトル、リスト)があり、それぞれの第一の要素に関数を適用したいときのために、それぞれの後、第二の要素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
    
  • Map - withのラッパーなので、リストを返すことが保証されています。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 -あなたは、各要素に関数を適用したいときのために、ネストされたリストの再帰的、構造。

    どれほど珍しいのかをお伝えするために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")
    
  • tapply -あなたがに関数を適用したいときのためにサブセットベクトルのサブセットとは、いくつかの他のベクター、通常の要因によって定義されています。

    ある種の* 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に共通する機能を(と精神に類似しているaggregatebyaveddplyしたがってその黒羊の状態、等)。

193
JoFrhwld 2010-08-18 09:20.

ちなみに、さまざまなplyr関数が基本*apply関数にどのように対応するかを次に示します(plyrWebページのイントロからplyrドキュメントまで)http://had.co.nz/plyr/)

Base function   Input   Output   plyr function 
---------------------------------------
aggregate        d       d       ddply + colwise 
apply            a       a/l     aaply / alply 
by               d       l       dlply 
lapply           l       l       llply  
mapply           a       a/l     maply / mlply 
replicate        r       a/l     raply / rlply 
sapply           l       a       laply 

の目標の1つは、plyr各関数に一貫した命名規則を提供し、関数名に入力データ型と出力データ型をエンコードすることです。また、からの出力dlply()は簡単に渡されldply()て有用な出力などを生成するという点で、出力の一貫性を提供します。

概念的には、学習plyrは基本*apply機能を理解することほど難しくありません。

plyrそして、reshape関数は私の毎日の使用でこれらの関数のほとんどすべてを置き換えました。しかし、Intro to Plyrドキュメントからも:

関連する関数tapplysweepに該当する機能を持っていないplyr、かつ有用なまま。merge要約を元のデータと組み合わせるのに役立ちます。

135
isomorphismes 2011-10-09 19:29.

のスライド21から http://www.slideshare.net/hadley/plyr-one-data-analytic-strategy:

(うまくいけばapply、@ Hadleyに対応し、@ Hadleyaaplyなどにaggregate対応することddplyは明らかです。同じスライドシェアのスライド20は、この画像から取得しない場合に明確になります。)

(左側が入力、上部が出力)

103
Assad Ebrahim 2014-04-25 14:20.

まず、ジョランの優れた答えから始めましょう。疑わしいことは、それを改善することができます。

次に、次のニーモニックは、それぞれの違いを覚えておくのに役立ちます。明らかなものもあれば、そうでないものもあります---これらについては、Joranの議論で正当化されます。

ニーモニック

  • lapplyあるリストは、リストまたはベクトルに作用し、リストを返す適用します。
  • sapply単純です lapply(関数はデフォルトで、可能な場合はベクトルまたは行列を返します)
  • vapply適用検証(リターンオブジェクトタイプを事前に指定することを可能にします)
  • rapply再帰リスト内のネストされたリスト、すなわちリストに適用されます
  • tapplyタグ付けされたタグのサブセットを識別する場合適用
  • applyあるジェネリック:行列の行または列に関数を適用する(または、より一般的には、アレイの寸法)

適切な背景の構築

apply家族を使用することがまだあなたにとって少し異質であると感じるならば、それはあなたが重要な視点を逃しているかもしれません。

これらの2つの記事が役立ちます。これらは、関数applyファミリーによって提供されている関数型プログラミング手法を動機付けるために必要な背景を提供します。

Lispのユーザーはすぐにパラダイムを認識します。Lispに慣れていない場合は、FPに頭を悩ませると、Rで使用するための強力な視点が得られます。これはapplyはるかに理にかなっています。

  • Advanced R:関数型プログラミング、HadleyWickham著
  • MichaelBartonによるRでの単純な関数型プログラミング
52
SabDeM 2015-08-28 16:28.

この投稿の(非常に優れた)回答の欠如byaggregate説明に気付いたので。これが私の貢献です。

沿って

byドキュメントに記載されているように関数は、のための「ラッパー」として、しかし可能tapply。の力は、処理できないbyタスクを計算したいときに発生しtapplyます。一例はこのコードです:

ct <- tapply(iris$Sepal.Width , iris$Species , summary )
cb <- by(iris$Sepal.Width , iris$Species , summary )

 cb
iris$Species: setosa Min. 1st Qu. Median Mean 3rd Qu. Max. 2.300 3.200 3.400 3.428 3.675 4.400 -------------------------------------------------------------- iris$Species: versicolor
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.000   2.525   2.800   2.770   3.000   3.400 
-------------------------------------------------------------- 
iris$Species: virginica Min. 1st Qu. Median Mean 3rd Qu. Max. 2.200 2.800 3.000 2.974 3.175 3.800 ct $setosa
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.300   3.200   3.400   3.428   3.675   4.400 

$versicolor Min. 1st Qu. Median Mean 3rd Qu. Max. 2.000 2.525 2.800 2.770 3.000 3.400 $virginica
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.200   2.800   3.000   2.974   3.175   3.800 

我々はこれらの2つのオブジェクトを印刷し、場合ctcb、私たちは「本質的に」同じ結果を持っており、唯一の違いはどのように示されており、さまざまでありclass、それぞれの属性byのためにcbarrayのためにct

私が言ったように、私byたちが使用できないときに力が発生しますtapply; 次のコードは一例です。

 tapply(iris, iris$Species, summary ) Error in tapply(iris, iris$Species, summary) : 
  arguments must have same length

Rは、引数は同じ長さでなければならないと言い、「因子summaryiris沿ってすべての変数のを計算したい」と言いますSpecies。しかし、Rは処理方法がわからないため、それを行うことができません。

by関数Rを使用するdata frameと、クラスに特定のメソッドをディスパッチしsummary、最初の引数の長さ(および型も)が異なっていても関数を機能させます。

bywork <- by(iris, iris$Species, summary ) bywork iris$Species: setosa
  Sepal.Length    Sepal.Width     Petal.Length    Petal.Width          Species  
 Min.   :4.300   Min.   :2.300   Min.   :1.000   Min.   :0.100   setosa    :50  
 1st Qu.:4.800   1st Qu.:3.200   1st Qu.:1.400   1st Qu.:0.200   versicolor: 0  
 Median :5.000   Median :3.400   Median :1.500   Median :0.200   virginica : 0  
 Mean   :5.006   Mean   :3.428   Mean   :1.462   Mean   :0.246                  
 3rd Qu.:5.200   3rd Qu.:3.675   3rd Qu.:1.575   3rd Qu.:0.300                  
 Max.   :5.800   Max.   :4.400   Max.   :1.900   Max.   :0.600                  
-------------------------------------------------------------- 
iris$Species: versicolor Sepal.Length Sepal.Width Petal.Length Petal.Width Species Min. :4.900 Min. :2.000 Min. :3.00 Min. :1.000 setosa : 0 1st Qu.:5.600 1st Qu.:2.525 1st Qu.:4.00 1st Qu.:1.200 versicolor:50 Median :5.900 Median :2.800 Median :4.35 Median :1.300 virginica : 0 Mean :5.936 Mean :2.770 Mean :4.26 Mean :1.326 3rd Qu.:6.300 3rd Qu.:3.000 3rd Qu.:4.60 3rd Qu.:1.500 Max. :7.000 Max. :3.400 Max. :5.10 Max. :1.800 -------------------------------------------------------------- iris$Species: virginica
  Sepal.Length    Sepal.Width     Petal.Length    Petal.Width          Species  
 Min.   :4.900   Min.   :2.200   Min.   :4.500   Min.   :1.400   setosa    : 0  
 1st Qu.:6.225   1st Qu.:2.800   1st Qu.:5.100   1st Qu.:1.800   versicolor: 0  
 Median :6.500   Median :3.000   Median :5.550   Median :2.000   virginica :50  
 Mean   :6.588   Mean   :2.974   Mean   :5.552   Mean   :2.026                  
 3rd Qu.:6.900   3rd Qu.:3.175   3rd Qu.:5.875   3rd Qu.:2.300                  
 Max.   :7.900   Max.   :3.800   Max.   :6.900   Max.   :2.500     

それは確かに機能し、結果は非常に驚くべきものです。これは、クラスのオブジェクトであるbyに沿って、そのSpecies(それらのそれぞれのために、と言う)を計算しsummary、各変数の。

最初の引数がであるdata frame場合、ディスパッチされた関数には、そのクラスのオブジェクトのメソッドが必要であることに注意してください。たとえば、このコードをmean関数とともに使用すると、まったく意味のない次のコードが作成されます。

 by(iris, iris$Species, mean) iris$Species: setosa
[1] NA
------------------------------------------- 
iris$Species: versicolor [1] NA ------------------------------------------- iris$Species: virginica
[1] NA
Warning messages:
1: In mean.default(data[x, , drop = FALSE], ...) :
  argument is not numeric or logical: returning NA
2: In mean.default(data[x, , drop = FALSE], ...) :
  argument is not numeric or logical: returning NA
3: In mean.default(data[x, , drop = FALSE], ...) :
  argument is not numeric or logical: returning NA

集計

aggregateこのように使用すると、別の使用方法と見なすことができますtapply

at <- tapply(iris$Sepal.Length , iris$Species , mean)
ag <- aggregate(iris$Sepal.Length , list(iris$Species), mean)

 at
    setosa versicolor  virginica 
     5.006      5.936      6.588 
 ag
     Group.1     x
1     setosa 5.006
2 versicolor 5.936
3  virginica 6.588

2つの直接的な違いは、の2番目の引数はリストであるaggregate 必要ありますtapply (必須ではありません)リストである可能性があり、の出力aggregateはデータフレームであり、の1つはでtapplyあるということarrayです。

の力はaggregatesubset引数を使用してデータのサブセットを簡単に処理できることと、tsオブジェクトのメソッドも備えていることformulaです。

これらの要素により、状況aggregateによってはそれを簡単に操作できるようになりtapplyます。以下にいくつかの例を示します(ドキュメントで入手可能)。

ag <- aggregate(len ~ ., data = ToothGrowth, mean)

 ag
  supp dose   len
1   OJ  0.5 13.23
2   VC  0.5  7.98
3   OJ  1.0 22.70
4   VC  1.0 16.77
5   OJ  2.0 26.06
6   VC  2.0 26.14

で同じことを達成できtapplyますが、構文が少し難しく、出力(状況によっては)が読みにくくなります。

att <- tapply(ToothGrowth$len, list(ToothGrowth$dose, ToothGrowth$supp), mean)

 att
       OJ    VC
0.5 13.23  7.98
1   22.70 16.77
2   26.06 26.14

使用できない、byまたはtapply使用しなければならない場合もありますaggregate

 ag1 <- aggregate(cbind(Ozone, Temp) ~ Month, data = airquality, mean)

 ag1
  Month    Ozone     Temp
1     5 23.61538 66.73077
2     6 29.44444 78.22222
3     7 59.11538 83.88462
4     8 59.96154 83.96154
5     9 31.44828 76.89655

tapply1回の呼び出しで前の結果を取得することはできませんが、Month各要素の平均を計算してから組み合わせる必要があります(関数na.rm = TRUEformulaメソッドにはaggregateデフォルトでna.action = na.omit)があるため、を呼び出す必要があることにも注意してください。

ta1 <- tapply(airquality$Ozone, airquality$Month, mean, na.rm = TRUE) ta2 <- tapply(airquality$Temp, airquality$Month, mean, na.rm = TRUE)

 cbind(ta1, ta2)
       ta1      ta2
5 23.61538 65.54839
6 29.44444 79.10000
7 59.11538 83.90323
8 59.96154 83.96774
9 31.44828 76.90000

しながら、by私たちは実際には次の関数呼び出しはエラーを返します(ただし、ほとんどの場合、それが供給機能に関連していることを達成することはできませんmean)。

by(airquality[c("Ozone", "Temp")], airquality$Month, mean, na.rm = TRUE)

また、結果が同じで、違いがクラス(および、表示/印刷の方法だけでなく、例、サブセット化の方法)オブジェクトにある場合もあります。

byagg <- by(airquality[c("Ozone", "Temp")], airquality$Month, summary)
aggagg <- aggregate(cbind(Ozone, Temp) ~ Month, data = airquality, summary)

前のコードは同じ目標と結果を達成します。ある時点で、どのツールを使用するかは個人的な好みとニーズの問題です。前の2つのオブジェクトには、サブセット化に関して非常に異なるニーズがあります。

35
jangorecki 2015-12-09 12:42.

各関数のユースケースの違いを説明するすばらしい答えがたくさんあります。パフォーマンスの違いについて説明している答えはありません。これは、さまざまな関数がさまざまな入力を期待し、さまざまな出力を生成するためですが、それらのほとんどは、シリーズ/グループで評価するという一般的な共通の目的を持っています。私の答えはパフォーマンスに焦点を当てるつもりです。上記のため、ベクトルからの入力作成はタイミングに含まれているため、apply関数も測定されません。

私は2つの異なる機能を一度にテストsumlengthました。テストされたボリュームは、入力で50M、出力で50Kです。私はまた、広く疑問を頼まれた時に使用されていなかった2つの現在人気のパッケージが含まれ、しているdata.tabledplyr。あなたが良いパフォーマンスを目指しているなら、両方とも間違いなく一見の価値があります。

library(dplyr)
library(data.table)
set.seed(123)
n = 5e7
k = 5e5
x = runif(n)
grp = sample(k, n, TRUE)

timing = list()

# sapply
timing[["sapply"]] = system.time({
    lt = split(x, grp)
    r.sapply = sapply(lt, function(x) list(sum(x), length(x)), simplify = FALSE)
})

# lapply
timing[["lapply"]] = system.time({
    lt = split(x, grp)
    r.lapply = lapply(lt, function(x) list(sum(x), length(x)))
})

# tapply
timing[["tapply"]] = system.time(
    r.tapply <- tapply(x, list(grp), function(x) list(sum(x), length(x)))
)

# by
timing[["by"]] = system.time(
    r.by <- by(x, list(grp), function(x) list(sum(x), length(x)), simplify = FALSE)
)

# aggregate
timing[["aggregate"]] = system.time(
    r.aggregate <- aggregate(x, list(grp), function(x) list(sum(x), length(x)), simplify = FALSE)
)

# dplyr
timing[["dplyr"]] = system.time({
    df = data_frame(x, grp)
    r.dplyr = summarise(group_by(df, grp), sum(x), n())
})

# data.table
timing[["data.table"]] = system.time({
    dt = setnames(setDT(list(x, grp)), c("x","grp"))
    r.data.table = dt[, .(sum(x), .N), grp]
})

# all output size match to group count
sapply(list(sapply=r.sapply, lapply=r.lapply, tapply=r.tapply, by=r.by, aggregate=r.aggregate, dplyr=r.dplyr, data.table=r.data.table), 
       function(x) (if(is.data.frame(x)) nrow else length)(x)==k)
#    sapply     lapply     tapply         by  aggregate      dplyr data.table 
#      TRUE       TRUE       TRUE       TRUE       TRUE       TRUE       TRUE 

# print timings
as.data.table(sapply(timing, `[[`, "elapsed"), keep.rownames = TRUE
              )[,.(fun = V1, elapsed = V2)
                ][order(-elapsed)]
#          fun elapsed
#1:  aggregate 109.139
#2:         by  25.738
#3:      dplyr  18.978
#4:     tapply  17.006
#5:     lapply  11.524
#6:     sapply  11.326
#7: data.table   2.686
28
John Paul 2016-05-16 17:59.

ここでのすべての素晴らしい答えにもかかわらず、言及するに値する2つの基本関数、便利なouter関数とあいまいなeapply関数があります。

アウター

outerより平凡なものとして隠されている非常に便利な関数です。outer説明のヘルプを読むと、次のようになります。

The outer product of the arrays X and Y is the array A with dimension  
c(dim(X), dim(Y)) where element A[c(arrayindex.x, arrayindex.y)] =   
FUN(X[arrayindex.x], Y[arrayindex.y], ...).

これは、線形代数タイプのものにのみ役立つように見えます。ただし、mapply2つの入力ベクトルに関数を適用するのと同じように使用できます。違いはmapply、最初の2つの要素に関数を適用し、次に次の2つの要素にouter関数を適用するのに対し、最初のベクトルの1つの要素と2番目のベクトルの要素のすべての組み合わせに関数を適用することです。例えば:

 A<-c(1,3,5,7,9)
 B<-c(0,3,6,9,12)

mapply(FUN=pmax, A, B)

> mapply(FUN=pmax, A, B)
[1]  1  3  6  9 12

outer(A,B, pmax)

 > outer(A,B, pmax)
      [,1] [,2] [,3] [,4] [,5]
 [1,]    1    3    6    9   12
 [2,]    3    3    6    9   12
 [3,]    5    5    6    9   12
 [4,]    7    7    7    9   12
 [5,]    9    9    9    9   12

値のベクトルと条件のベクトルがあり、どの値がどの条件を満たしているかを確認したい場合に、これを個人的に使用しました。

eapply

eapplylapplyリスト内のすべての要素に関数を適用するのではなく、環境内のすべての要素に関数を適用することを除いて、は似ています。たとえば、グローバル環境でユーザー定義関数のリストを検索する場合は、次のようにします。

A<-c(1,3,5,7,9)
B<-c(0,3,6,9,12)
C<-list(x=1, y=2)
D<-function(x){x+1}

> eapply(.GlobalEnv, is.function)
$A [1] FALSE $B
[1] FALSE

$C [1] FALSE $D
[1] TRUE 

率直に言って、私はこれをあまり使用しませんが、多くのパッケージを構築している場合や、多くの環境を作成している場合は、便利な場合があります。

25
Noname 2014-11-06 14:00.

言及する価値があるかもしれませんaveaveあるtapplyのは、優しいいとこ。データフレームに直接プラグインできる形式で結果を返します。

dfr <- data.frame(a=1:20, f=rep(LETTERS[1:5], each=4))
means <- tapply(dfr$a, dfr$f, mean)
##  A    B    C    D    E 
## 2.5  6.5 10.5 14.5 18.5 

## great, but putting it back in the data frame is another line:

dfr$m <- means[dfr$f]

dfr$m2 <- ave(dfr$a, dfr$f, FUN=mean) # NB argument name FUN is needed!
dfr
##   a f    m   m2
##   1 A  2.5  2.5
##   2 A  2.5  2.5
##   3 A  2.5  2.5
##   4 A  2.5  2.5
##   5 B  6.5  6.5
##   6 B  6.5  6.5
##   7 B  6.5  6.5
##   ...

基本パッケージには、aveデータフレーム全体のように機能するものはありません(データフレームの場合のbyようtapplyに)。しかし、あなたはそれをごまかすことができます:

dfr$foo <- ave(1:nrow(dfr), dfr$f, FUN=function(x) { x <- dfr[x,] sum(x$m*x$m2)
})
dfr
##     a f    m   m2    foo
## 1   1 A  2.5  2.5    25
## 2   2 A  2.5  2.5    25
## 3   3 A  2.5  2.5    25
## ...
12
vonjd 2017-06-17 06:03.

私は最近、かなり便利なsweep関数を発見し、完全を期すためにここに追加しました。

掃く

基本的な考え方は、配列を行または列ごとにスイープし、変更された配列を返すことです。例はこれを明らかにします(出典:datacamp):

行列があり、それを列ごとに標準化するとします。

dataPoints <- matrix(4:15, nrow = 4)

# Find means per column with `apply()`
dataPoints_means <- apply(dataPoints, 2, mean)

# Find standard deviation with `apply()`
dataPoints_sdev <- apply(dataPoints, 2, sd)

# Center the points 
dataPoints_Trans1 <- sweep(dataPoints, 2, dataPoints_means,"-")

# Return the result
dataPoints_Trans1
##      [,1] [,2] [,3]
## [1,] -1.5 -1.5 -1.5
## [2,] -0.5 -0.5 -0.5
## [3,]  0.5  0.5  0.5
## [4,]  1.5  1.5  1.5

# Normalize
dataPoints_Trans2 <- sweep(dataPoints_Trans1, 2, dataPoints_sdev, "/")

# Return the result
dataPoints_Trans2
##            [,1]       [,2]       [,3]
## [1,] -1.1618950 -1.1618950 -1.1618950
## [2,] -0.3872983 -0.3872983 -0.3872983
## [3,]  0.3872983  0.3872983  0.3872983
## [4,]  1.1618950  1.1618950  1.1618950

注意:この単純な例では、もちろん同じ結果をより簡単に達成できます。
apply(dataPoints, 2, scale)

3
Sebastian 2020-03-20 21:22.

最近CRANでリリースされた折りたたみパッケージでは、一般的な適用機能のほとんどを2つの機能に圧縮しようとしました。

  1. dapply(Data-Apply)は、matrixとdata.framesの行または(デフォルト)列に関数を適用し、(デフォルト)同じタイプで同じ属性を持つオブジェクトを返します(各計算の結果がアトミックである場合を除くdrop = TRUE)。パフォーマンスはlapplydata.frame列の場合と同等でありapply、行列の行または列の場合よりも約2倍高速です。並列処理はmclapply(MACの場合のみ)を介して利用できます。

構文:

dapply(X, FUN, ..., MARGIN = 2, parallel = FALSE, mc.cores = 1L, 
       return = c("same", "matrix", "data.frame"), drop = TRUE)

例:

# Apply to columns:
dapply(mtcars, log)
dapply(mtcars, sum)
dapply(mtcars, quantile)
# Apply to rows:
dapply(mtcars, sum, MARGIN = 1)
dapply(mtcars, quantile, MARGIN = 1)
# Return as matrix:
dapply(mtcars, quantile, return = "matrix")
dapply(mtcars, quantile, MARGIN = 1, return = "matrix")
# Same for matrices ...
  1. BYは、ベクトル、行列、およびdata.frameメソッドを使用した分割-適用-結合コンピューティングのS3ジェネリックです。tapplybyおよびよりも大幅に高速ですaggregate(ただしplyr、大規模なデータでdplyrは、よりも高速です)。

構文:

BY(X, g, FUN, ..., use.g.names = TRUE, sort = TRUE,
   expand.wide = FALSE, parallel = FALSE, mc.cores = 1L,
   return = c("same", "matrix", "data.frame", "list"))

例:

# Vectors:
BY(iris$Sepal.Length, iris$Species, sum)
BY(iris$Sepal.Length, iris$Species, quantile)
BY(iris$Sepal.Length, iris$Species, quantile, expand.wide = TRUE) # This returns a matrix 
# Data.frames
BY(iris[-5], iris$Species, sum) BY(iris[-5], iris$Species, quantile)
BY(iris[-5], iris$Species, quantile, expand.wide = TRUE) # This returns a wider data.frame BY(iris[-5], iris$Species, quantile, return = "matrix") # This returns a matrix
# Same for matrices ...

グループ化変数のリストもに提供できgます。

パフォーマンスについて話す:崩壊の主な目標は、Rで高性能プログラミングを促進し、split-apply-combineを一緒に超えていくことです。この目的のため、パッケージには、C ++ベースの高速な汎用的な機能のフルセットを持っているfmeanfmedianfmodefsumfprodfsdfvarfminfmaxffirstflastfNobsfNdistinctfscalefbetweenfwithinfHDbetweenfHDwithinflagfdifffgrowth。これらは、データの1回のパスでグループ化された計算を実行します(つまり、分割や再結合は行いません)。

構文:

fFUN(x, g = NULL, [w = NULL,] TRA = NULL, [na.rm = TRUE,] use.g.names = TRUE, drop = TRUE)

例:

v <- iris$Sepal.Length f <- iris$Species

# Vectors
fmean(v)             # mean
fmean(v, f)          # grouped mean
fsd(v, f)            # grouped standard deviation
fsd(v, f, TRA = "/") # grouped scaling
fscale(v, f)         # grouped standardizing (scaling and centering)
fwithin(v, f)        # grouped demeaning

w <- abs(rnorm(nrow(iris)))
fmean(v, w = w)      # Weighted mean
fmean(v, f, w)       # Weighted grouped mean
fsd(v, f, w)         # Weighted grouped standard-deviation
fsd(v, f, w, "/")    # Weighted grouped scaling
fscale(v, f, w)      # Weighted grouped standardizing
fwithin(v, f, w)     # Weighted grouped demeaning

# Same using data.frames...
fmean(iris[-5], f)                # grouped mean
fscale(iris[-5], f)               # grouped standardizing
fwithin(iris[-5], f)              # grouped demeaning

# Same with matrices ...

パッケージビネットでは、ベンチマークを提供します。高速関数を使用したプログラミングは、dplyrまたはdata.table使用したプログラミングよりも、特に小さいデータだけでなく、大きいデータでも大幅に高速です。

Related questions

MORE COOL STUFF

「水曜日」シーズン1の中心には大きなミステリーがあります

「水曜日」シーズン1の中心には大きなミステリーがあります

Netflixの「水曜日」は、典型的な10代のドラマ以上のものであり、実際、シーズン1にはその中心に大きなミステリーがあります.

ボディーランゲージの専門家は、州訪問中にカミラ・パーカー・ボウルズが輝くことを可能にした微妙なケイト・ミドルトンの動きを指摘しています

ボディーランゲージの専門家は、州訪問中にカミラ・パーカー・ボウルズが輝くことを可能にした微妙なケイト・ミドルトンの動きを指摘しています

ケイト・ミドルトンは、州の夕食会と州の訪問中にカミラ・パーカー・ボウルズからスポットライトを奪いたくなかった、と専門家は言う.

一部のファンがハリー・スタイルズとオリビア・ワイルドの「非常に友好的な」休憩が永続的であることを望んでいる理由

一部のファンがハリー・スタイルズとオリビア・ワイルドの「非常に友好的な」休憩が永続的であることを望んでいる理由

一部のファンが、オリビア・ワイルドが彼女とハリー・スタイルズとの間の「難しい」が「非常に友好的」な分割を恒久的にすることを望んでいる理由を見つけてください.

エリザベス女王の死後、ケイト・ミドルトンはまだ「非常に困難な時期」を過ごしている、と王室の専門家が明らかにする 

エリザベス女王の死後、ケイト・ミドルトンはまだ「非常に困難な時期」を過ごしている、と王室の専門家が明らかにする&nbsp;

エリザベス女王の死後、ケイト・ミドルトンが舞台裏で「非常に困難な時期」を過ごしていたと伝えられている理由を調べてください.

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セント ヘレナ島のジェイコブズ ラダーは 699 段の真っ直ぐ上る階段で、頂上に到達すると証明書が発行されるほどの難易度です。

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

Total War:Warhammer:Kotakuレビュー

Total War:Warhammer:Kotakuレビュー

私はこのゲームを嫌う準備ができていました。先週の前に、Total War:Warhammerについての私の考えがありました:それでもここに私は、私の手にある完成品であり、私は変わった男です。

涙の道:軍事化された帝国主義勢力がスタンディングロックキャンプを占領

涙の道:軍事化された帝国主義勢力がスタンディングロックキャンプを占領

スタンディングロックスー族のメンバーと水の保護者は、ノースダコタ州のスタンディングロックにあるオセティサコウィンキャンプを去ります。(Twitter経由のCNNスクリーンショット)火と煙がスカイラインを覆い、スタンディングロックスー族のメンバーと水の保護者が、聖なるものを守りながら建てた家、オセティサコウィン(セブンカウンシルファイアーズ)キャンプから行進し、太鼓を打ち、歌い、祈りました。ダコタアクセスパイプラインとしても知られる「ブラックスネーク」からの土地。

シアーズとKマートはイヴァンカ・トランプの商品を自分たちで取り除いています

シアーズとKマートはイヴァンカ・トランプの商品を自分たちで取り除いています

写真:APシアーズとKマートは、イヴァンカ・トランプのトランプホームアイテムのコレクションも、誰も購入したくないために削除しました。シアーズとKマートの両方の親会社であるシアーズホールディングスは、土曜日のABCニュースへの声明で、彼らが気にかけていると辛抱強く説明しましたトランプラインを売り続けるにはお金を稼ぐことについてあまりにも多く。

ポテトチップスでたった10分でスペインのトルティーヤを作る

ポテトチップスでたった10分でスペインのトルティーヤを作る

伝統的なスペインのトルティーヤは通常、オリーブオイルで柔らかくなるまで調理されたポテトから始まります(30分以上かかる場合があります)が、ケトルで調理されたポテトチップスの助けを借りてわずか10分でテーブルに置くことができます。上のビデオはすべてがバラバラにならないように裏返す方法を含め、レシピ全体を説明しますが、必要なのは4〜5個の卵と3カップのケトルチップスだけです。

ケイト・ミドルトンとウィリアム王子は、彼らが子供たちと行っているスパイをテーマにした活動を共有しています

ケイト・ミドルトンとウィリアム王子は、彼らが子供たちと行っているスパイをテーマにした活動を共有しています

ケイト・ミドルトンとウィリアム王子は、子供向けのパズルの本の序文を書き、ジョージ王子、シャーロット王女、ルイ王子と一緒にテキストを読むと述べた.

事故で押しつぶされたスイカは、動物を喜ばせ水分補給するために野生生物保護団体に寄付されました

事故で押しつぶされたスイカは、動物を喜ばせ水分補給するために野生生物保護団体に寄付されました

Yak's Produce は、数十個のつぶれたメロンを野生動物のリハビリ専門家であるレスリー グリーンと彼女のルイジアナ州の救助施設で暮らす 42 匹の動物に寄付しました。

デミ・ロヴァートは、新しいミュージシャンのボーイフレンドと「幸せで健康的な関係」にあります: ソース

デミ・ロヴァートは、新しいミュージシャンのボーイフレンドと「幸せで健康的な関係」にあります: ソース

8 枚目のスタジオ アルバムのリリースに向けて準備を進めているデミ ロヴァートは、「スーパー グレート ガイ」と付き合っている、と情報筋は PEOPLE に確認しています。

Plathville の Kim と Olivia Plath が数年ぶりに言葉を交わすことへようこそ

Plathville の Kim と Olivia Plath が数年ぶりに言葉を交わすことへようこそ

イーサン プラスの誕生日のお祝いは、TLC のウェルカム トゥ プラスビルのシーズン 4 のフィナーレで、戦争中の母親のキム プラスと妻のオリビア プラスを結びつけました。

仕事の生産性を高める 8 つのシンプルなホーム オフィスのセットアップのアイデア

仕事の生産性を高める 8 つのシンプルなホーム オフィスのセットアップのアイデア

ホームオフィスのセットアップ術を極めよう!AppExert の開発者は、家族全員が一緒にいる場合でも、在宅勤務の技術を習得しています。祖父や曽祖父が共同家族で暮らしていた頃の記憶がよみがえりました。

2022 年、私たちのデジタル ライフはどこで終わり、「リアル ライフ」はどこから始まるのでしょうか?

20 年前のタイムトラベラーでさえ、日常生活におけるデジタルおよびインターネットベースのサービスの重要性に驚くことでしょう。MySpace、eBay、Napster などのプラットフォームは、高速化に焦点を合わせた世界がどのようなものになるかを示してくれました。

ニューロマーケティングの秘密科学

ニューロマーケティングの秘密科学

マーケティング担当者が人間の欲望を操作するために使用する、最先端の (気味が悪いと言う人もいます) メソッドを探ります。カートをいっぱいにして 3 桁の領収書を持って店を出る前に、ほんの数点の商品を買いに行ったことはありませんか? あなたは一人じゃない。

地理情報システムの日: GIS 開発者として学ぶべき最高の技術スタック

地理情報システムの日: GIS 開発者として学ぶべき最高の技術スタック

私たちが住んでいる世界を確実に理解するには、データが必要です。ただし、空間参照がない場合、このデータは地理的コンテキストがないと役に立たなくなる可能性があります。

Language