グループ化関数(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

ケイト・ブランシェットは3日間一緒に夫と一緒に寝て、25年経ってもまだ夫と結婚しています

ケイト・ブランシェットは3日間一緒に夫と一緒に寝て、25年経ってもまだ夫と結婚しています

ケイト・ブランシェットは、夫に会ったとき、典型的な交際のアドバイスに逆らいました。

マイケルシーンが非営利の俳優である理由

マイケルシーンが非営利の俳優である理由

マイケルシーンは非営利の俳優ですが、それは正確にはどういう意味ですか?

ホールマークスターのコリンエッグレスフィールドがRomaDramaLiveでスリル満点のファンと出会う![エクスクルーシブ]

ホールマークスターのコリンエッグレスフィールドがRomaDramaLiveでスリル満点のファンと出会う![エクスクルーシブ]

特徴的なスターのコリン・エッグレスフィールドは、RomaDrama Liveでのスリル満点のファンとの出会いについて料理しました!加えて、大会での彼のINSPIREプログラム。

「たどりつけば」をオンラインでストリーミングできない理由

「たどりつけば」をオンラインでストリーミングできない理由

ノーザンエクスポージャーが90年代の最も人気のある番組の1つになった理由を確認するには、Blu-rayまたはDVDプレーヤーをほこりで払う必要があります。

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

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

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

ドミニカのボイリング湖:アクセスは簡単ではありませんが、ハイキングする価値があります

ドミニカのボイリング湖:アクセスは簡単ではありませんが、ハイキングする価値があります

ドミニカのボイリング湖は、世界で2番目に大きいボイリング湖です。そこにたどり着くまでのトレッキングは大変で長いですが、努力する価値は十分にあります。

私たちの水をきれいに保つのを助けるためにあなたの髪を寄付してください

私たちの水をきれいに保つのを助けるためにあなたの髪を寄付してください

サロンからのヘアトリミングや個人的な寄付は、油流出を吸収して環境を保護するのに役立つマットとして再利用できます。

ホワイトハウスの最も記憶に残る結婚式を見てください

ホワイトハウスの最も記憶に残る結婚式を見てください

過去200年以上の間にホワイトハウスで結婚したのはほんの数人です。彼らは誰でしたか、そしてそこで結婚式を獲得するために何が必要ですか?

Netflixのジョエルマクヘイルとのジョエルマクヘイルショーは、ジョエルマクヘイルにぴったりの車を復活させます

Netflixのジョエルマクヘイルとのジョエルマクヘイルショーは、ジョエルマクヘイルにぴったりの車を復活させます

ジョエル・マクヘイル、マイク・コルター(スクリーンショット:Netflix)「私の神よ、これは1つのことを変えます。」これは、ジョエル・マクヘイルとのジョエル・マクヘイルショーの最後のジョークです。リアリティ番組の嘲笑と寛大なスナキネスの時間は、なじみのある顔を見つけます。

チームロケットは20年ぶりにポケモンシリーズでアッシュを破った

チームロケットは20年ぶりにポケモンシリーズでアッシュを破った

画像経由:@pancakeparadox(Twitter)。1997年にポケモンシリーズが初公開されて以来、チームロケット(またはラテンアメリカではチームロケット)として知られる悪役のグループは、何度もアッシュに直面してきました。

今週の科学技術でトランプがめちゃくちゃになったことすべて

今週の科学技術でトランプがめちゃくちゃになったことすべて

画像:ゲッティ私たち全員が千年もの間生きていて、私たちの体が燃える風によってほこりと長引く悲鳴だけに押し流されたと考えるのは驚くべきことです。私たちがそうしていないことを除いて、それはトランプ政権の最初の週の終わりであり、驚くほど多くの恐ろしいことがすでに起こっています。

あなたの「マイクロピッグ」が代わりに通常のピッグになってしまったとしても驚かないでください

あなたの「マイクロピッグ」が代わりに通常のピッグになってしまったとしても驚かないでください

そして今、あることを手に入れていると思っていたが、まったく別のことをしてしまった男の話。CBSニュースは、彼女が「ミニブタ」であるという誤ったふりをしてエスターを養子にしたカナダ人のスティーブジェンキンスの心温まる物語をもたらします。これは、特にせいぜいゴールデンレトリバーまたはセントバーナードをストラップします。

Zendaya Wishes Boyfriend Tom Holland Happy Birthday with Cuddly Photo: He 'Makes Me the Happiest'

Zendaya Wishes Boyfriend Tom Holland Happy Birthday with Cuddly Photo: He 'Makes Me the Happiest'

Zendaya shared a sweet photo in honor of boyfriend Tom Holland's 26th birthday Wednesday

小さな女性:脳卒中を患った後に病院から解放されたアトランタのジューシーな赤ちゃん:「まだ癒し」

小さな女性:脳卒中を患った後に病院から解放されたアトランタのジューシーな赤ちゃん:「まだ癒し」

シーレン「Ms.JuicyBaby」ピアソンは、先月脳卒中で入院した後、「もう一度たくさんのことをする方法を学ばなければならない」ため、言語療法を受けていることを明らかにしました。

エマストーンは彼女のクリフサイドマリブビーチハウスを420万ドルでリストアップしています—中を見てください!

エマストーンは彼女のクリフサイドマリブビーチハウスを420万ドルでリストアップしています—中を見てください!

オスカー受賞者の世紀半ばの家には、3つのベッドルーム、2つのバス、オーシャンフロントの景色があります。

ジーニー・メイ・ジェンキンスは、母乳育児の経験の中で、彼女は「本当に、本当に落ち込んでいる」と言います

ジーニー・メイ・ジェンキンスは、母乳育児の経験の中で、彼女は「本当に、本当に落ち込んでいる」と言います

ジーニー・メイ・ジェンキンスは、生後4か月の娘、モナコに母乳育児をしていると語った。

投資ノート:Bioscout AU$300万シード

投資ノート:Bioscout AU$300万シード

Bioscoutは、農家を運転席に置くという使命を負っています。Artesian(GrainInnovate)やUniseedと並んで、最新のシードラウンドでチームを支援できることをうれしく思います。問題真菌症による重大な作物の損失は、農民にとって試練であることが証明されています。

リトルマーケットリサーチ1| 2022年のクイックグリンプス遠隔医療市場

リトルマーケットリサーチ1| 2022年のクイックグリンプス遠隔医療市場

遠隔医療は、パンデミック後の時代では新しいものではなく、時代遅れの分野でもありません。しかし、業界を詳しく見ると、需要と供給の強力な持続可能性と、米国で絶え間ない革命となる強力な潜在的成長曲線を示しています。

スタートアップ資金調達環境:タイのスタートアップエコシステムの次は何ですか?

スタートアップ資金調達環境:タイのスタートアップエコシステムの次は何ですか?

2021年は、世界的なベンチャーキャピタル(VC)の資金調達にとって記録的な年でした。DealStreetAsiaによると、東南アジアも例外ではなく、この地域では年間で記録的な25の新しいユニコーンが採掘されました。

ムーアの法則を超えて

ムーアの法則を超えて

計算に対する私たちの欲求とムーアの法則が提供できるものとの間には、指数関数的に増大するギャップがあります。私たちの文明は計算に基づいています—建築と想像力の現在の限界を超える技術を見つけなければなりません。

Language