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列のマトリックスを作成したことを確認します。 これを検証するために、 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



ます。



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



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



All Articles