applyファミリー

apply ファミリーの関数には apply のほかに tapply mapply lapply sapply などがある。行列あるいはリストに対して、一括して演算を行うときに利用する。

関数働き
apply(x,i,f)行列・データフレーム(x)に対して、各行(i = 1)または各列(i = 2)ごとに演算(f)を行う。
lapply(x,f)リスト(x)の各要素に対して演算(f)を行う。実行結果をリスト型で返す。
sapply(x,f)リスト(x)の各要素に対して演算(f)を行う。実行結果をベクトル型で返す。

apply

apply 関数の基本的な使い方

行列型またはデータフレーム型のデータに対して、各行または各列に対して、同種の演算を一括に行うときに apply を利用する。apply の 1 つ目の引数にはデータを代入する。2 つ目の引数には 1 または 2 を代入する。1 は各行を意味し、2 は各列を意味する。また、3 つ目の引数には適用したい演算(関数名)を与える。

x <- matrix(c(12.1, 3.44, 0.1, 3, 12, 33.1, 1.1, 23), nrow = 2)

x
##       [,1] [,2] [,3] [,4]
## [1,] 12.10  0.1 12.0  1.1
## [2,]  3.44  3.0 33.1 23.0


# calculate totals
apply(x, 1, sum)
## [1] 25.30 62.54

# calculate averages
apply(x, 2, mean)
## [1]  7.77  1.55 22.55 12.05

上で用いた summean などの関数は R に標準実装されている関数である。これを自作関数に置き換えることも可能である。例えば、以下の用にすると、i には各行のデータが代入される。

x <- matrix(c(12.1, 3.44, 0.1, 3, 12, 33.1, 1.1, 23), nrow = 2)

# get the maximum numbers from each row
M <- apply(x, 1, function(y) {
    # `y` contains data of the each row of `x`
    m <- max(y)
    return(m)
  }
)
## [1] 12.1 33.1


# use for-loop instead of apply function
M <- NULL
for (j in 1:nrow(x)) {
  y <- x[j, ]
  m <- max(y)
  M <- c(M, m)
}
M
## [1] 12.1 33.1

apply 関数に引数を与える方法

apply に自作関数を適用させたい場合、時には外部から引数を与える必要がある。一般に、apply 関数は 3 つの引数を受けとるが、4 つ目以降に代入された引数は、自動的に 3 番目に指定した関数に引き渡される。

x <- c(1, 3, 5, 7)
y <- c(2, 4, 6, 8)

mat <- matrix(1:10, ncol = 2)

d <- apply(mat, 1, function(i, px = x, py = y) {
  a <- i[1] + 2 * i[2]
  # `px` is `x` in this apply function.
  # `py` is `y` in this apply function.
  b <- mean(px) * mean(py)
  return(c(a, b))
}, x, y)

d
##      [,1] [,2] [,3] [,4] [,5]
## [1,]   13   16   19   22   25
## [2,]   20   20   20   20   20

lapply

lapply はリスト型に対して、何かを一括演算するときに利用する。リスト型のデータは、1、2、… のように番号付けられているため、行列のように行または列を指定しない。そのため、行列を指定しない分、引数は入力データと演算処理を行う関数の 2 つだけである。

x <- list(1:10,11:20,21:30)
x
## [[1]]
##  [1]  1  2  3  4  5  6  7  8  9 10
## [[2]]
##  [1] 11 12 13 14 15 16 17 18 19 20
## [[3]]
##  [1] 21 22 23 24 25 26 27 28 29 30

lapply(x,sum)
## [[1]]
## [1] 55
## [[2]]
## [1] 155
## [[3]]
## [1] 255

sapply

lapply と同じ使い方で、同じ機能を持つ。ただし、戻り値は lapply ではリスト型であるのに対して、sapply はベクトル型となる。

x <- list(1:10,11:20,21:30)

lapply(x, sum) 
## [[1]]
## [1] 55
## 
## [[2]]
## [1] 155
## 
## [[3]]
## [1] 255


sapply(x, sum) 
## [1]  55 155 255


as.numeric(lapply(x, sum))
## [1]  55 155 255