Rで "map" pyを実行したいときはいつでも、私はapply
ファミリーの関数を使おうとします。
しかし、{sapply
、lapply
など}が入力/グループ化された入力に関数をどのように適用するか、出力がどのようになるか、さらには入力がどのようになる可能性があるのか - 欲しいものが手に入るまで、たいていの場合、私はそれらすべてをただ通過するだけです。
誰かがいつどれを使うかを説明できますか?
私の現在の(たぶん正しくない/不完全な)理解は….
sapply(vec, f)
:入力はベクトルです。出力はベクトル/行列です。ここで、要素i
はf(vec[i])
で、f
が複数要素の出力を持つ場合は行列を与えます。
lapply(vec, f)
:sapply
と同じですが、出力はリストですか?
apply(matrix, 1/2, f)
:入力は行列です。出力はベクトルです。ここで、要素i
はfです(行列の行/列i)。tapply(vector, grouping, f)
:出力は行列/配列です。ここで、行列/配列内の要素はベクトルのグループ化f
にあるg
の値で、g
は行/列名にプッシュされます。by(dataframe, grouping, f)
:g
をグループにしましょう。グループ/データフレームの各列にf
を適用します。各列にグループ化とf
の値をきれいに表示します。aggregate(matrix, grouping, f)
:by
に似ていますが、出力をきれいに印刷する代わりに、aggregateはすべてをデータフレームに固定します。副次的な質問:私はまだplyrや変形を学んでいません - plyr
またはreshape
はこれらすべてを完全に置き換えるのでしょうか?
Rには、ヘルプファイル(例えば?apply
)に正しく記述されている* apply関数がたくさんあります。しかし、それらの十分なものはありますが、useRは最初のうちどれが自分の状況に適しているのか、あるいはそれらすべてを覚えているのかを判断するのが難しいかもしれません。彼らは「ここでは* apply関数を使うべきだ」という一般的な意味を持つかもしれませんが、最初からそれらをすべてまっすぐにしておくのは難しいかもしれません。
*他の回答で述べたように、* applyファミリーの機能の大部分は非常に人気のあるplyr
パッケージによってカバーされているという事実にもかかわらず、基本関数は有用であり、知る価値があります。
この答えはある種の 道標 新しいuseRが彼らの特定の問題に対して正しい* apply関数にそれらを向けるのを助けるために働くことを意図しています。注意してください、これは ではありません 単にRのドキュメンテーションを逆流させるか置き換えるためのものです!この答えがどの* apply関数があなたの状況に合っているかを決めるのを手助けすることを望んでいます、そしてそれをさらに研究するのはあなた次第です。 1つの例外を除いて、パフォーマンスの違いは解決されません。
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
を調べてください。
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 - リストの各要素に順番に関数を適用したいが、リストではなく vector backが必要な場合 _
自分で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 - いくつかのデータ構造(例えばベクトル、リスト)があり、それぞれの最初の要素に、そして次にそれぞれの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
Map - SIMPLIFY = FALSE
を付けたmapply
へのラッパーで、リストを返すことが保証されています。
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 - ベクトルの サブセット に関数を適用したい場合、サブセットは他のベクトル、通常は因子によって定義されます。
*の黒い羊は、ある種の家族に当てはまります。ヘルプファイルでの "ragged array"というフレーズの使用は少々 混乱を招く になることがありますが、実際は非常に単純です。
ベクトル:
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で一般的なsplit-apply-combine関数(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
plyr
の目標の1つは、各関数に一貫した命名規則を提供し、入力データ型と出力データ型を関数名にエンコードすることです。また、dlply()
からの出力は、有用な出力を生成するためにldply()
に簡単に渡すことができるという点で、出力の一貫性を提供します。
概念的には、plyr
を学ぶことは、基本の*apply
関数を理解することより難しくありません。
plyr
とreshape
関数は、私が毎日使う中でこれらの関数のほとんどすべてを置き換えました。しかし、PlyrからIntroへの文書からも:
関連する関数
tapply
とsweep
は、plyr
には対応する関数がなく、便利なままです。merge
は、要約を元のデータと組み合わせるのに便利です。
スライド21から http://www.slideshare.net/hadley/plyr-one-data-analytic-strategy :
(apply
が@ Hadleyのaaply
に対応し、aggregate
が@ Hadleyのddply
に対応することが明らかになっています。等、同じスライドシェアのスライド20では、この画像から取得できない場合が明確になります。)
(左が入力、上が出力)
まず始めに Joranのすばらしい答え - 疑問があればそれを改善できる。
それから、次のニーモニックはそれぞれの違いを思い出すのを助けるかもしれません。いくつかは明白ですが、他の人はあまりそうではないかもしれません---これらのためにあなたはJoranの議論で正当化を見つけるでしょう。
ニーモニック
lapply
はlist applyで、リストまたはベクトルに作用してリストを返します。sapply
はsimplelapply
です(関数はデフォルトで可能な場合はベクトルまたは行列を返します)vapply
は検証済みの適用(戻りオブジェクト型を事前指定可能にする)rapply
は、ネストされたリスト、つまりリスト内のリストに適用されるrecursiveです。tapply
は、タグがサブセットを識別する場所にtagged applyですapply
は総称:行列の行または列(またはより一般的には配列の次元)に関数を適用します正しい背景を構築する
apply
ファミリーを使うことがまだあなたにとってちょっと異質な気分になれば、それはあなたが重要な視点を欠いているということかもしれません。
この2つの記事が参考になります。それらは、関数のapply
ファミリーによって提供されている 関数型プログラミング技法 を動機付けるために必要な背景を提供します。
LISPのユーザはすぐにこのパラダイムを認識するでしょう。 LISPに慣れていないのであれば、一旦FPに慣れてしまえば、Rで使用するための強力な視点が得られます - そしてapply
はもっと理にかなっています。
この投稿の(非常に優れた)回答には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
for cb
およびarray
for ct
。
私が言ったように、by
の力は、tapply
を使用できないときに生じます。次のコードは一例です。
tapply(iris, iris$Species, summary )
Error in tapply(iris, iris$Species, summary) :
arguments must have same length
Rは、引数は同じ長さでなければならない、たとえば「summary
のすべての変数のiris
を因子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つの直接的な違いは、aggregate
mustの2番目の引数がリストであるのに対し、tapply
can(必須ではない)がリストであり、 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
1回の呼び出しでtapply
を使用して以前の結果を取得することはできませんが、各要素の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
のように動作するものはありません(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], ...).
これは、これが線形代数型のものにのみ有用であるように見せます。しかし、2つの入力ベクトルに関数を適用するためにmapply
のように使うことができます。違いは、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
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
関数を発見し、完全を期すためにここにそれを追加しました:
スイープ
基本的な考え方は、行方向または列方向に配列を介してsweepを実行し、変更された配列を返すことです。例を見ればわかります(source: datacamp )。
行列があり、列方向に 標準化 itしたいとしましょう。
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
注意:この簡単な例では、当然のことながら同じ結果をより簡単に達成できます。apply(dataPoints, 2, scale)