グループ化関数(タップ、by、集計)と *ファミリを適用する
質問
私がRで何か「マップ」pyをしたいときはいつでも、私は通常、で関数を使用しようとします apply
家族。
しかし、私はそれらの違いを完全に理解したことはありませんでした - どのように{sapply
, lapply
, 、など}関数を入力/グループ化された入力、出力がどのように見えるか、または入力が何であるかにさえ適用します。
誰かがいつどれを使用するかを説明できますか?
私の現在(おそらく間違っている/不完全)理解は...
sapply(vec, f)
: :入力はベクトルです。出力はベクトル/マトリックスであり、ここでは要素ですi
はf(vec[i])
, 、あなたにマトリックスを与えますf
マルチエレメント出力がありますlapply(vec, f)
: : と同じsapply
, 、しかし、出力はリストですか?apply(matrix, 1/2, f)
: :入力はマトリックスです。出力はベクトルであり、要素ですi
f(マトリックスのrow/col i)tapply(vector, grouping, f)
: :出力はマトリックス/配列であり、マトリックス/配列の要素はの値ですf
グループでg
ベクトルの、そしてg
行/col名に押し込まれますby(dataframe, grouping, f)
: : させてg
グループになります。申し込みf
グループ/データフレームの各列に。のグループ化と価値をきれいに印刷しますf
各列で。aggregate(matrix, grouping, f)
: : に似ているby
, 、しかし、出力をきれいに印刷する代わりに、Aggregateはすべてをデータフレームに貼り付けます。
サイドの質問:私はまだPlyrやReshapeを学んでいません - plyr
また reshape
これらすべてを完全に交換しますか?
解決
rヘルプファイルで適切に説明されている多くの *適用関数があります(例: ?apply
)。ただし、最初のユーザーが自分の状況に適したものを決定することや、それらすべてを覚えていることを決定するのが困難な場合があります。彼らは「ここで *適用機能を使用する必要がある」という一般的な感覚を持っているかもしれませんが、最初はそれらをすべてまっすぐに保つのは難しいかもしれません。
*適用ファミリの機能の多くは非常に人気があるという事実にもかかわらず(他の回答に記載されています) plyr
パッケージ、ベース機能は引き続き有用であり、知る価値があります。
この答えは、ある種のように機能することを目的としています SINDPOST 新しいユーザーが特定の問題に正しい *機能を適用するのを助けるために。注意してください、これはそうです いいえ 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マトリックスの行/列の手段または合計が必要な場合は、高度に最適化された稲妻を調査してください
colMeans
,rowMeans
,colSums
,rowSums
.Lapply - リストの各要素に関数を適用し、リストを取り戻す場合。
これは、他の多くの *適用関数の主力です。コードを剥がすと、しばしば見つかります
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
基本的に同じことを行い、返された各マトリックスを単一の長いベクトルとして扱います。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
マップライ - いくつかのデータ構造(ベクトル、リストなど)がある場合、それぞれの最初の要素に関数を適用し、次にそれぞれの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
地図 - ラッパーへ
mapply
とSIMPLIFY = FALSE
, 、したがって、リストを返すことが保証されています。Map(sum, 1:5, 1:5, 1:5) [[1]] [1] 3 [[2]] [1] 6 [[3]] [1] 9 [[4]] [1] 12 [[5]] [1] 15
repply - あなたがの各要素に関数を適用したいときのために ネストされたリスト 構造、再帰的。
どれほど珍しいことについてのアイデアを与えるために
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")
タプリー - 関数を適用したいときのために サブセット ベクトルとサブセットは、通常、他のベクトルによって定義されます。通常は因子です。
*の黒い羊は、ある種の家族を適用します。ヘルプファイルの「ラグ付き配列」というフレーズの使用は、少しすることができます 紛らわしい, 、しかし、それは実際には非常に簡単です。
ベクトル:
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
, など)したがって、その黒い羊の状態。
他のヒント
サイドノートでは、ここにさまざまな方法があります plyr
関数はベースに対応します *apply
関数(イントロからPLYR Webページの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
関数は、私の毎日の使用において、これらの関数のほぼすべてを置き換えました。しかし、イントロからPLYRドキュメントまで:
関連関数
tapply
とsweep
対応する関数はありませんplyr
, 、そして有用なままです。merge
要約と元のデータを組み合わせるのに役立ちます。
スライド21から http://www.slideshare.net/hadley/plyr-one-data-analytic-strategy:
(うまくいけば、それは明らかです apply
@Hadley'sに対応します aaply
と aggregate
@Hadley'sに対応します ddply
など。同じスライドシェアのスライド20は、この画像から取得できない場合に明確になります。)
(左側は入力、上部は出力です)
最初のスタート ジョランの優れた答え - 何でも疑いのあるものはそれを良くすることができます。
次のニーモニックは、それぞれの区別を思い出すのに役立つかもしれません。明らかな人もいますが、他の人はそれほど少ないかもしれません---これらのために、あなたはジョランの議論に正当化を見つけるでしょう。
ニーモニック
lapply
aです リスト リストまたはベクトルにどのような動作を適用し、リストを返します。sapply
aです 単純lapply
(機能は、可能な場合はベクトルまたはマトリックスを返すデフォルトです)vapply
aです 検証済みの適用 (戻りオブジェクトタイプを事前指定させることを許可します)rapply
aです 再帰 ネストされたリスト、つまりリスト内のリストを申請しますtapply
aです タグ付き タグがサブセットを識別する場合に適用しますapply
は ジェネリック: :マトリックスの行または列に関数を適用します(または、より一般的には、配列の寸法に)
適切な背景を構築します
を使用する場合 apply
家族はまだあなたにとって少しエイリアンを感じていますが、それはあなたが重要な視点を見逃しているかもしれません。
これらの2つの記事が役立ちます。彼らは動機付けに必要な背景を提供します 機能的なプログラミング技術 それはによって提供されています apply
機能の家族。
LISPのユーザーは、すぐにパラダイムを認識します。 LISPに精通していない場合、FPの周りに頭を獲得したら、Rで使用する強力な視点を獲得しました - そして apply
もっと理にかなっています。
- 高度なR:機能プログラミング, 、ハドリー・ウィッカム
- rの単純な機能プログラミング, 、マイケル・バートンによる
この投稿の(非常に優れた)答えがないことに気付いたので by
と aggregate
説明。これが私の貢献です。
に
by
文書に記載されているように、機能しているように、「ラッパー」としての機能 tapply
. 。のパワー by
タスクを計算したいときに発生します tapply
処理できません。 1つの例はこのコードです。
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つのオブジェクトを印刷すると、 ct
と cb
, 、私たちは「本質的に」同じ結果を持っています、そして、唯一の違いはそれらの表示方法と異なるものです class
それぞれ属性 by
にとって cb
と array
にとって ct
.
私が言ったように、の力 by
使用できないときに発生します tapply
;次のコードは1つの例です。
tapply(iris, iris$Species, summary )
Error in tapply(iris, iris$Species, summary) :
arguments must have same length
Rは、議論には同じ長さが必要だと言います。 summary
すべての変数の iris
要因に沿って Species
":しかし、それはそれがどのように扱うかわからないので、それはそれをすることができません。
とともに 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
各変数の。
最初の引数がaの場合に注意してください 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
の間、データフレームです tapply
です array
.
のパワー aggregate
データのサブセットを簡単に処理できるということです subset
議論とそれには方法があります 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
以前の結果を取得することはできません tapply
1回の呼び出しでは、平均を計算する必要があります Month
各要素について、それらを結合します(また、 na.rm = TRUE
, 、 なぜなら formula
の方法 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つのオブジェクトは、サブセットに関して非常に異なるニーズを持っています。
各関数のユースケースの違いを議論する素晴らしい答えがたくさんあります。回答のどれも、パフォーマンスの違いについて議論していません。これは、さまざまな機能がさまざまな入力を期待し、さまざまな出力を生成する合理的な原因ですが、それらのほとんどはシリーズ/グループによって評価する一般的な共通の目的を持っています。私の答えはパフォーマンスに焦点を当てるでしょう。上記のため、ベクトルからの入力作成はタイミングに含まれています。 apply
関数は測定されません。
2つの異なる機能をテストしました sum
と length
すぐに。テストされたボリュームは、入力で50m、出力で50kです。また、質問が尋ねられた時点では広く使用されていなかった2つの現在人気のあるパッケージも含まれています。 data.table
と dplyr
. 。あなたが良いパフォーマンスを目指しているなら、どちらも間違いなく見る価値があります。
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
言及する価値があるかもしれません ave
. ave
は 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
データフレーム全体(as 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
## ...
ここにはすべての素晴らしい答えにもかかわらず、言及するに値する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], ...).
これは、これが線形代数タイプのものにのみ役立つように見えるようにします。ただし、同じように使用できます mapply
入力の2つのベクトルに関数を適用します。違いはそれです mapply
最初の2つの要素に関数を適用し、次に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
eapply
のようなものです lapply
それを除き、リスト内のすべての要素に関数を適用するのではなく、環境内のすべての要素に関数を適用します。たとえば、グローバル環境でユーザー定義機能のリストを見つけたい場合:
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
率直に言って、私はこれをあまり使用していませんが、多くのパッケージを構築したり、多くの環境を作成している場合は、便利になる可能性があります。
私は最近、かなり便利なことを発見しました sweep
機能して、完全性のためにここに追加します。
掃く
基本的なアイデアはそうです 掃く 配列の行または列ごとに、変更された配列を返します。例としてこれが明確になります(出典: データサンプ):
あなたがマトリックスを持っていて、したいとしましょう 標準化します それは列に伴い:
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,"-")
print(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
# 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
NB:この簡単な例では、同じ結果がもちろんより簡単に達成できます
apply(dataPoints, 2, scale)