サーチ…


備考

*applyファミリーの関数は、 forループの抽象です。 forループとの比較*apply関数には次の利点があります。

  1. 書き込むコードが少なくて済みます。
  2. 反復カウンタはありません。
  3. 中間結果を格納するために一時変数を使用しません。

しかしforループはより一般的であり、 *apply関数を使用することは必ずしも簡単ではない複雑な計算を実現するために、より多くの制御を与えることが*applyます。

forループと*apply関数の関係については、 forループのドキュメントを参照for

*apply加盟家族のメンバー

*applyファミリには、主に返される出力の種類に基づいて異なる、同じ原則の複数のバリアントが含まれています。

関数入力出力
apply matrixdata.frame 、またはarray ベクトルまたは行列(返される各要素の長さに応じて)
sapply ベクトルまたはlist ベクトルまたは行列(返される各要素の長さに応じて)
lapply ベクトルまたはlist list
vapply ベクトルまたは `list ベクトルまたは行列(返される各要素の長さに応じて)ユーザー指定のクラス
mapply 複数のベクトル、 listsまたは組み合わせ list

これらの各関数の使用方法については、「例」を参照してください。

適用時に匿名関数を使用する

applyは、配列や行列のマージン上の関数(おそらく匿名の関数)を評価するために使われapply

このアイデアを説明するためにirisデータセットを使用しましょう。 irisデータセットは、3種から150の花を測定しています。このデータセットの構造を見てみましょう:

> head(iris)

  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1         5.1          3.5          1.4         0.2  setosa
2         4.9          3.0          1.4         0.2  setosa
3         4.7          3.2          1.3         0.2  setosa
4         4.6          3.1          1.5         0.2  setosa
5         5.0          3.6          1.4         0.2  setosa
6         5.4          3.9          1.7         0.4  setosa

さて、あなたはこれらの変数のそれぞれの平均値を知りたいことを想像してください。これを解決する1つの方法は、 forループを使用することforが、Rプログラマはしばしばapplyを使用applyことを好みapply (理由は理由を参照してください)。

> apply(iris[1:4], 2, mean)

Sepal.Length  Sepal.Width Petal.Length  Petal.Width 
    5.843333     3.057333     3.758000     1.199333
  • 最初のパラメータでは、 meanは数値データに対してのみ機能するため、最初の4列のみを含めるようにirisをサブセット化しています。
  • 第2のパラメータ値2我々は唯一の(Cアレイ×Rの第二の添え字)カラム上で動作することを示しています。 1は行手段を与える。

同様に、より意味のある値を計算することができます。

# standard deviation
apply(iris[1:4], 2, sd)
# variance
apply(iris[1:4], 2, var)

警告 :Rには、列と行の合計を計算するのに適した組み込み関数がいくつかありrowMeanscolMeansrowMeansrowMeansを意味します。

ここでは、より意味のある別のタスクを実行しましょう: 0.5より大きい値に対してのみ平均を計算しましょう。そのために、私たちは独自のmean関数を作成します。

> our.mean.function <- function(x) { mean(x[x > 0.5]) }
> apply(iris[1:4], 2, our.mean.function)

Sepal.Length  Sepal.Width Petal.Length  Petal.Width 
    5.843333     3.057333     3.758000     1.665347

Petal.Widthの平均の違いに注意してください)

しかし、コードの残りの部分でこの関数を使用したくない場合はどうすればよいでしょうか?次に、無名関数を使用して、次のようなコードを書くことができます:

apply(iris[1:4], 2, function(x) { mean(x[x > 0.5]) })

これまで見てきたように、 applyを使用して、1行だけを使用してデータセットの列または行に対して同じ操作を実行することができます。

注意applyは指定された関数の結果の長さに応じて非常に異なる出力を返すので、対話的に作業していない場合には最適な選択ではないかもしれません。他の*apply家族機能のいくつかは、もう少し予測可能です(備考参照)。

バルクファイル読み込み

同様のプロセスで十分に構造化されたファイル名で操作される必要のある多数のファイルについては、

まず、アクセスするファイル名のベクトルを作成する必要があります。これには複数のオプションがあります。

  • paste0()でベクトルを手動で作成する

     files <- paste0("file_", 1:100, ".rds")
    
  • list.files()をファイルタイプの正規表現検索語で使用する場合、同じタイプの他のファイルがディレクトリにある場合、正規表現( 正規表現 )の知識が必要です。

     files <- list.files("./", pattern = "\\.rds$", full.names = TRUE)
    

Xは、使用されるファイル命名形式の一部のベクトルです。

lapplyは各応答をリストの要素として出力します。

readRDS.rdsファイルに固有であり、プロセスの適用に応じて変更されます。

my_file_list <- lapply(files, readRDS)

これはテストからのforループより必ずしも高速ではありませんが、すべてのファイルを明示的に割り当てずにリストの要素にすることができます。

最後に、複数のパッケージを一度に読み込む必要があることがよくあります。このトリックは、私たちがインポートしたいすべてのライブラリにlibrary()を適用することで、簡単に行うことができます:

lapply(c("jsonlite","stringr","igraph"),library,character.only=TRUE)

複数の `data.frames`(` lapply`、 `mapply`)を組み合わせると、

この練習では、4つのブートストラップ線形回帰モデルを生成し、これらのモデルのサマリーを1つのデータフレームに結合します。

library(broom)

#* Create the bootstrap data sets
BootData <- lapply(1:4,
                   function(i) mtcars[sample(1:nrow(mtcars),
                                             size = nrow(mtcars),
                                             replace = TRUE), ])

#* Fit the models
Models <- lapply(BootData,
                 function(BD) lm(mpg ~ qsec + wt + factor(am),
                                 data = BD))

#* Tidy the output into a data.frame
Tidied <- lapply(Models,
                 tidy)

#* Give each element in the Tidied list a name
Tidied <- setNames(Tidied, paste0("Boot", seq_along(Tidied)))

この時点で、名前をdata.frameに挿入するには2つの方法があります。

#* Insert the element name into the summary with `lapply`
#* Requires passing the names attribute to `lapply` and referencing `Tidied` within
#* the applied function.
Described_lapply <- 
 lapply(names(Tidied),
        function(nm) cbind(nm, Tidied[[nm]]))

Combined_lapply <- do.call("rbind", Described_lapply)

#* Insert the element name into the summary with `mapply`
#* Allows us to pass the names and the elements as separate arguments.
Described_mapply <- 
 mapply(
  function(nm, dframe) cbind(nm, dframe),
  names(Tidied),
  Tidied,
  SIMPLIFY = FALSE)

Combined_mapply <- do.call("rbind", Described_mapply)

あなたがmagrittrスタイルパイプのファンであれば、(モデルオブジェクト自体のような中間オブジェクトのどれかが必要な場合はそうするのは賢明ではありませんが)タスク全体を単一のチェーンで実行できます。

library(magrittr)
library(broom)
Combined <- lapply(1:4,
                   function(i) mtcars[sample(1:nrow(mtcars),
                                             size = nrow(mtcars),
                                             replace = TRUE), ]) %>%
 lapply(function(BD) lm( mpg ~ qsec + wt + factor(am), data = BD)) %>%
 lapply(tidy) %>%
 setNames(paste0("Boot", seq_along(.))) %>%
 mapply(function(nm, dframe) cbind(nm, dframe),
        nm = names(.),
        dframe = .,
        SIMPLIFY = FALSE) %>%
 do.call("rbind", .)

組み込みfunctionalsの使用

組み込み機能:lapply()、sapply()、mapply()

Rには機能が組み込まれています。その中でもっともよく知られているものは機能の適用ファミリです。最も一般的な適用関数のいくつかについて以下に説明します。

  • lapply() =は引数としてリストをとり、指定された関数をリストに適用します。
  • sapply()と同じ= lapply()が、ベクトルまたは行列に出力を簡素化しようとします。
    • vapply() =出力オブジェクトの型を指定する必要があるsapply()変種。
  • mapply() =のようなlapply()が、指定された関数への入力として複数のベクトルを渡すことができます。 sapply()ように単純化することができます。
    • Map()は、 SIMPLIFY = FALSE mapply()へのエイリアスです。

lapply()

lapply()は、2つの異なる反復で使用できます。

  • lapply(variable, FUN)
  • lapply(seq_along(variable), FUN)
# Two ways of finding the mean of x
set.seed(1)
df <- data.frame(x = rnorm(25), y = rnorm(25))
lapply(df, mean)
lapply(seq_along(df), function(x) mean(df[[x]))

サプリー()

sapply()は、その出力をベクトルまたは行列に解決しようとします。

# Two examples to show the different outputs of sapply()
sapply(letters, print)  ## produces a vector
x <- list(a = 1:10, beta = exp(-3:3), logic = c(TRUE,FALSE,FALSE,TRUE))
sapply(x, quantile)  ## produces a matrix

mapply()

mapply()同じようにlapply()しますが、入力として複数のベクトルを取ることができます(多変量の場合はm)。

mapply(sum, 1:5, 10:6, 3) # 3 will be "recycled" by mapply

ユーザー定義ファンクショナルの使用

ユーザー定義ファンクショナル

ユーザーはさまざまな程度の複雑さで独自の機能を作成できます。以下の例は、Hadley WickhamのFunctionalsからのものです。

randomise <- function(f) f(runif(1e3))
        
lapply2 <- function(x, f, ...) {
    out <- vector("list", length(x))
    for (i in seq_along(x)) {
        out[[i]] <- f(x[[i]], ...)
    }
    out
}

最初のケースでは、 randomiseは単一の引数f受け取り、それをUniformランダム変数のサンプルで呼び出します。等価性を証明するために、以下のset.seedを呼び出します。

set.seed(123)
randomise(mean)
#[1] 0.4972778
    
set.seed(123)
mean(runif(1e3))
#[1] 0.4972778


set.seed(123)
randomise(max)
#[1] 0.9994045

set.seed(123)
max(runif(1e3))
#[1] 0.9994045

2番目の例は、functionalsを使用してリスト( x )の各要素に操作( f )を適用するbase::lapply再実装です。 ...パラメータを使用すると、 mean関数のna.rmオプションなど、 fに追加の引数を渡すことができます。

lapply(list(c(1, 3, 5), c(2, NA, 6)), mean)
# [[1]]
# [1] 3
# 
# [[2]]
# [1] NA

lapply2(list(c(1, 3, 5), c(2, NA, 6)), mean)
# [[1]]
# [1] 3
# 
# [[2]]
# [1] NA


lapply(list(c(1, 3, 5), c(2, NA, 6)), mean, na.rm = TRUE)
# [[1]]
# [1] 3
# 
# [[2]]
# [1] 4

lapply2(list(c(1, 3, 5), c(2, NA, 6)), mean, na.rm = TRUE)
# [[1]]
# [1] 3
# 
# [[2]]
# [1] 4


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow