これは、apply、sapply、およびlapplyの使用に関する入門記事であり、Rを初めて使用するか、これらの機能に慣れていない人に最適です。 Rでの作業時によく使用されるため、適用ファミリーの関数の使用例をいくつか示します。
データセットでこれら3つの方法を比較しました。 サンプルが生成され、それらに適用されました。 アプリケーションの結果がどのように異なるかを知りたかった。
マトリックスを返すテストベンチも使用されました。 3列で約30行ありました。 次のようになりました。
method1 method2 method3 [1,] 0.05517714 0.014054038 0.017260447 [2,] 0.08367678 0.003570883 0.004289079 [3,] 0.05274706 0.028629661 0.071323030 [4,] 0.06769936 0.048446559 0.057432519 [5,] 0.06875188 0.019782518 0.080564474 [6,] 0.04913779 0.100062929 0.102208706
そのようなデータは、3つのセットを作成するために
rnorm
を使用してシミュレートできます。 最初の-平均0、2番目-平均2、3番目-平均5、および30行。
m <- matrix(data=cbind(rnorm(30, 0), rnorm(30, 2), rnorm(30, 5)), nrow=30, ncol=3)
適用する
いつ申請するか? 大量の注文データを処理する必要がある場合。 たとえば、何らかのマトリックス形式の一連の平均。 適用されるべき操作:情報を取得する、おそらく変換、サブセットの選択、データに対する操作。
データブロック(データフレームタイプ)を使用する場合、すべてのデータは同じタイプである必要があります。そうでない場合、変換が適用されます。 これは、まさにあなたが必要とするものであるかもしれませんし、そうでないかもしれません。 データブロックに文字列/アルファベットおよび数値データが含まれている場合、数値データは文字列に変換され、数値に対する操作では予期しない結果が生じる可能性があります。
疑いもなく、Rで作業する場合、適用の
apply
正当化される状況は非常に頻繁に発生するため、この機能の機能に慣れる価値があるため、生産性が大幅に向上します。 必要な適用ファミリの機能は、データ、それを使用して何をする必要があるか、結果がどのように見えるかによって異なります。 これらの例の後、正しい選択をするのが少し簡単になるかもしれません。
まず、平均値がそれぞれ0、2、5の3列のマトリックスを作成したことを確認します。 これを検証するために、
apply
と
mean
関数を使用し
apply
。 指定する2番目の引数は、関数を適用する次元(列または行)に適用されます。 この場合、最後に3つの数値を取得したいので、2番目の引数として2を渡して、列を操作する
apply
に
apply
。 しかし、説明を間違えましょう:
apply(m, 1, mean)
# [1] 2.408150 2.709325 1.718529 0.822519 2.693614 2.259044 1.849530 2.544685 2.957950 2.219874 #[11] 2.582011 2.471938 2.015625 2.101832 2.189781 2.319142 2.504821 2.203066 2.280550 2.401297 #[21] 2.312254 1.833903 1.900122 2.427002 2.426869 1.890895 2.515842 2.363085 3.049760 2.027570
2番目の引数として1を渡すと、各行の平均である30個の値が取得されます。 望んでいた3つの数字ではありません。 もう一度試してみましょう。
apply(m, 2, mean)
#[1] -0.02664418 1.95812458 4.86857792
素晴らしい。 ご覧のとおり、各列の平均は予想どおり約0、2、5です。
独自の機能
この負の数値を見た後、正の数値のみで作業したいことに気づいたとしましょう。
apply
再度
apply
して、各列に負の数がいくつあるかを調べましょう。
apply(m, 2, function(x) length(x[x<0]))
#[1] 14 1 0
したがって、最初の列に14個の負の数があり、2番目に1つ、3番目に1つではありません。 上記の平均および単位標準偏差を持つ3つの正規分布に対して、多かれ少なかれ予想されます。
ここでは、ある種の組み込みではなく、
apply
の呼び出しで直接定義された単純な関数を使用しました。 関数で戻り値を指定しなかったことに注意してください。 実際、関数はサブセットを使用して0未満のすべての要素
を選択し、
length
を使用してそれらをカウントします。 この関数は1つの引数を取ります。この引数は
任意に指定します。 この場合、
は行列の列の1つです。 それは単一列の行列ですか、それとも単なるベクトルですか? 見てみましょう:
apply(m, 2, function(x) is.matrix(x))
#[1] FALSE FALSE FALSE
マトリックスではありません。 ここでは、関数の定義は必要ありません
is.matrix
関数を渡すことができます。1つの引数を取り、既に作成されているためです。 予想どおり、これらがベクトルであることを確認しましょう。
apply(m, 2, is.vector)
#[1] TRUE TRUE TRUE
では、なぜ長さ関数でラップする必要があったのですか? 適用のために独自のハンドラを定義する場合、関数で使用するために少なくとも入力変数の名前を設定する必要があります。
apply(m, 2, length(x[x<0]))
#Error in match.fun(FUN) : object 'x' not found
この関数では、
値を参照しますが、Rはそれについて何も知らないため、エラーが発生します。 他の要因もここで役割を果たしますが、簡単にするために、コードは関数でラップする必要があることに注意してください。 たとえば、正の値のみの平均を見てみましょう。
apply(m, 2, function(x) mean(x[x>0]))
#[1] 0.4466368 2.0415736 4.8685779
sapplyとlapplyの使用
これらの2つの関数は同様に機能し、データセットをリストまたはベクトルとして表し、特定の関数を各要素に適用します。
場合によっては、線形データ変換以外のものが必要になります。 たとえば、現在の値を5回前の値と比較したいとします。 このために
rollapply
を使用する価値があるかもしれませんが、インデックス化された値のセットを渡すことで
sapply
または
lapply
を実行するのは、完全ではありませんが簡単な方法です。
ここでは、リストまたはデータベクトルで機能する
sapply
を適用します。
sapply(1:3, function(x) x^2)
#[1] 1 4 9
lapply
非常に似ていますが、ベクトルではなくリストを返します。
lapply(1:3, function(x) x^2)
#[[1]] #[1] 1 # #[[2]] #[1] 4 # #[[3]] #[1] 9
sapply
simplify=FALSE
を
sapply
と、リストも取得できます。
sapply(1:3, function(x) x^2, simplify=F)
#[[1]] #[1] 1 # #[[2]] #[1] 4 # #[[3]] #[1] 9
unlist
を
lapply
使用してベクトルを取得することもできます。
unlist(lapply(1:3, function(x) x^2))
#[1] 1 4 9
データと期待される結果に意味がある場合は、
lapply
と
sapply
を使用するのが最適です。 リストが必要な場合は、
lapply
使用し
lapply
。 ベクトルが
sapply
場合。
回避策
いずれにせよ、簡単な方法は、
sapply
ベクトル
sapply
を渡して関数を記述し、入力データの構造について仮定することです。
mean
例をもう一度見てみましょう。
sapply(1:3, function(x) mean(m[,x]))
[1] -0.02664418 1.95812458 4.86857792
この関数では、列インデックス(1、2、3)を渡します。これは、データに変数
m
が存在することを示しています。 迅速な解決策としては良いのですが、全体としてはそれほどではなく、将来的にはサポートの大きな問題になる可能性が高いです。
データを関数に引数として渡し、すべての適用関数が追加のパラメーターを渡すために使用する特別な引数「...」を使用することで、少し改善できます。
sapply(1:3, function(x, y) mean(y[,x]), y=m)
#[1] -0.02664418 1.95812458 4.86857792
今回は、関数に2つの引数
と
ます。 前と同様に、
変数は、それが何であれ、
sapply
するデータを示します。 オプションの
sapply
引数を使用して変数
を
sapply
ます。
この場合、
m
を入力に渡し、
sapply
呼び出すときに変数
明示的に設定し
sapply
。 これは厳密に必要というわけではありませんが、コードの理解と保守が容易です。
の値は、
sapply
関数を呼び出すたびに同じに
sapply
ます。
この方法でインデックス付き引数を渡すことは強くお勧めしません。これはエラーの原因であり、他の人があなたのコードを読んだときに読みにくいです。
これらの例がお役に立てば幸いです。