Rでapply、sapply、lapplyを使用する

これは、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列のマトリックスを作成したことを確認します。 これを検証するために、 applymean関数を使用しapply 。 指定する2番目の引数は、関数を適用する次元(列または行)に適用されます。 この場合、最後に3つの数値を取得したいので、2番目の引数として2を渡して、列を操作するapplyapply 。 しかし、説明を間違えましょう:

 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=FALSEsapplyと、リストも取得できます。
 sapply(1:3, function(x) x^2, simplify=F) 

 #[[1]] #[1] 1 # #[[2]] #[1] 4 # #[[3]] #[1] 9 

unlistlapply使用してベクトルを取得することもできます。

 unlist(lapply(1:3, function(x) x^2)) 

 #[1] 1 4 9 

データと期待される結果に意味がある場合は、 lapplysapplyを使用するのが最適です。 リストが必要な場合は、 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ます。

この方法でインデックス付き引数を渡すことは強くお勧めしません。これはエラーの原因であり、他の人があなたのコードを読んだときに読みにくいです。

これらの例がお役に立てば幸いです。

Source: https://habr.com/ru/post/J274611/


All Articles