スタートページJavaScript他言語R言語

apply系 配列内の計算


apply ファミリの概要

apply は、主に配列内での一括処理を記述するための関数です。

                           # 行列
                              #      [,1] [,2] [,3]
m <- matrix(c(11, 12, 13,     # [1,]   11   12   13
              21, 22, 23),    # [2,]   21   22   23
            nrow=2, byrow=T)
v <- apply(m, 1, sum)      # 各行の合計、列方向への計算
v                             # 36 66

apply には、次のファミリがあります。

  allay 標準
  lallay 各行の計算 出力はリスト形式
  sapply 各行の計算 出力はベクトル形式
  tapply 処理行の選択など複雑な条件指定ができる。ここでは省略します。
  mapply  applyの多変量版。ここでは省略します。

lapply, sapply

機能が比較的単純な sapply, 1apply から説明します。

一般形:lapply(入力配列, 加工関数)
    sapply(入力配列, 加工関数)

入力形式での結果

# ===== リスト形式 =====
a <- list(c(11, 12, 13),
          c(21, 22, 23))
ba <- sapply(a, sum)
ba             # 36・66
ba[1]          # 36 ┐
ba[2]          # 66 ├ ★直観と一致
ba[1] + ba[2]  # 102 ┘

# ===== 行列形式 =====
                              #        [,1] [,2] [,3]
m <- matrix(c(11, 12, 13,     # [1,]    11   12   13
              21, 22, 23),    # [2,]    21   22   23
            nrow=2, byrow=T)
bm <- sapply(m, sum)
bm             # 11・21・12・22・13・23 ★ m の内容
bm[1] + bm[2]  # 32

# ===== データフレーム形式 =====
                             # 縦横が転置
df <- data.frame(              #    c1 c2
              c1 = c(11, 12, 13),  # 1  11 21
              c2 = c(21, 22, 23))  # 2  12 22
                                   # 3  13 23
bf <- sapply(df, sum)
bf                  # c1:36 c2:66
bf[1] + bf[2]      # c1:102
bf["c1"]            # c1: 36
bf["c2"]            # c2: 66
bf["c1"] + bf["c2"] # c1:102

sapply/lapply での出力方式の違い

sapply: [i]、 [[i]] 可
# ====== sapply =======
a <- list(c(11, 12, 13),
          c(21, 22, 23))
ba <- sapply(a, sum)
ba                  # 36・66
ba[1]               # 36 OK
ba[1] + ba[2]       # 102 OK
ba[[1]]             # 36 OK
ba[[1]] + ba[[2]]   # 102 OK
lapply: [[i]] のみ可
# ====== iapply =======
a <- list(c(11, 12, 13),
          c(21, 22, 23))
ba <- iapply(a, sum)
ba                   # 1. 36 2.66
ba[[1]]              # 36  OK
ba[[1]] + ba[[2]]    # 102 OK
ba[1]                # 1. 36
ba[1] + ba[2]        # ★エラー

apply

一般形:apply(入力配列, MARGIN, 加工関数)

# ===== リスト形式 ===== エラーになる
# a <- list(c(11, 12, 13),
#           c(21, 22, 23))
# ba <- apply(a, 1, sum)  ★ここでエラーになる
# 

# ===== 行列形式 =====
                              #        [,1] [,2] [,3]
m <- matrix(c(11, 12, 13,     # [1,]    11   12   13
              21, 22, 23),    # [2,]    21   22   23
            nrow=2, byrow=T)
bm <- apply(m, 1, sum)
bm             # 36・66
bm[1]               # 36
bm[1] + bm[2]       # 102
bm[[1]]             # 36
bm[[1]] + bm[[2]]   # 102

# ===== データフレーム形式 =====
                             # 縦横が転置
df <- data.frame(                  #    c1 c2
              c1 = c(11, 12, 13),  # 1  11 21
              c2 = c(21, 22, 23))  # 2  12 22
                                   # 3  13 23
bf <- apply(df, 2, sum)  # 転置しているので MARGIN = 2 とする
bf                  # 36・66
bf[1]               # 36
bf[1] + bf[2]       # 102
bf[[1]]             # 36
bf[[1]] + bf[[2]]   # 102
bf["c1"]            # c1: 36
bf["c1"] + bf["c2"] # c1: 102

(注)一次元加工以外での関数

一般に apply での関数は、sum や mean など、行あるいは列を一次元配列とした加工が主ですが、 sqrt のような要素単位での加工もできます。

●sqrt

                              #        [,1] [,2] [,3]
m <- matrix(c(11, 12, 13,     # [1,]    11   12   13
              21, 22, 23),    # [2,]    21   22   23
            nrow=2, byrow=T)
bm <- apply(m, 1, sqrt)
bm        #        [, 1]    [, 2]
          # [1, ] 3.316625 4.582576
          # [2, ] 3.464102 4.690416
          # [3, ] 3.605551 4.795832
bm[1, 2]  # 4.582576

bm <- apply(m, 2, aqrt)    # こちらが入力データと同じ順序になる。
bm        #        [, 1]    [, 2]    [, 3]
          # [1, ] 3.316625	3.464102	3.605551
          # [2, ] 4.582576	4.690416	4.795832
bm[1, 2]  # 3.464102

●sort(降順)

                              #        [,1] [,2] [,3]
m <- matrix(c(11, 12, 13,     # [1,]    11   12   13
              21, 22, 23),    # [2,]    21   22   23
            nrow=2, byrow=T)
bm <- apply(m, 1, sort, decreasing = TRUE)
bm        #        [, 1]    [, 2]
          # [1, ]   23        23
          # [2, ]   12        22
          # [3, ]   11        21
bm[1, 2]  # 23
bm <- apply(m, 2, sort, decreasing = TRUE)    # こちらが入力データと同じ順序になる。
bm        #        [, 1]    [, 2]    [, 3]
          # [1, ]   21       22       23
          # [2, ]   11       12       13
bm[1, 2]  # 22

自作関数

apply グループでは、加工関数を自作することができます。

一般形:apply(DATA, MARGIN, function(x) { }) (単純処理)
    apply(DATA, MARGIN,         (オプション処理)
      function(x) {
        : z <- …
        return(z)
      }
    )

単純処理

apply(m, 1, sum) と同じです。
function(x) の x は、名称は任意ですが、sum(x) のように、関数は ( ) を付ける必要があり、その引数と同一名になります。

# ========= 入力データ
                              #        [,1] [,2] [,3]
m <- matrix(c(11, 12, 13,     # [1,]    11   12   13
              21, 22, 23),    # [2,]    21   22   23
            nrow=2, byrow=T)
                             # 縦横が転置
df <- data.frame(                  #    c1 c2
              c1 = c(11, 12, 13),  # 1  11 21
              c2 = c(21, 22, 23))  # 2  12 22
                                   # 3  13 23
# ========= 例1 apply(m, 1, sum) と同じ
bm <- apply(m, 1, function(x) { sum(x) })
bm[1]                 # 36
bm[1] + bm[2]         # 102

bf <- apply(df, 2, function(x) { sum(x) })   # 転置しているので MARGIN = 2 とする
bf[1]                 # c1: 36
bf[1] + bf[2]         # c1: 102
bf["c1"]              # c1: 36
bf["c1"] + bf["c2"]   # c1: 102

オプション処理(インライン)

例えば sum(x) の結果に y=100 を加えるような処理です。
function の引数

# ========= 入力データ
                              #        [,1] [,2] [,3]
m <- matrix(c(11, 12, 13,     # [1,]    11   12   13
              21, 22, 23),    # [2,]    21   22   23
            nrow=2, byrow=T)
                             # 縦横が転置
df <- data.frame(                  #    c1 c2
              c1 = c(11, 12, 13),  # 1  11 21
              c2 = c(21, 22, 23))  # 2  12 22

# ========= 例A 計算結果に y=100(function内指定) を加える
bm <- apply(m, 1,
        function(x) {
            y <- 100
            z <- sum(x) + y
            return(z);
        }
     )
bm[1]                 # 136
bm[1] + bm[2]         # 302

bf <- apply(df, 2, 
        function(x) {
            y <- 100
            z <- sum(x) + y
            return(z);
        }
     )
bf[1]                 # c1: 136
bf[1] + bf[2]         # c1: 302
bf["c1"]              # c1: 136
bf["c1"] + bf["c2"]   # c1: 302

# ========= 例B 外部で与えた変数を内部でそのまま使う
y <- 100
bm <- apply(m, 1,
        function(x) {
            z <- sum(x) + y
            return(z);
        }
     )
bm[1]                 # 136
bm[1] + bm[2]         # 302

自作関数を定義しておき、外部から呼び出す

# ======= DATA を外部で設定
自作関数 <- function(x, y) {
    z <- sum(x) + y
    return(z)
}
df <- data.frame(                  #    c1 c2
              c1 = c(11, 12, 13),  # 1  11 21
              c2 = c(21, 22, 23))  # 2  12 22
bf = apply(df, 2, 自作関数, 100)   # 100 を y=100 としてもよい
bf[1] + bf[2]         # c1: 302
bf["c1"] + bf["c2"]   # c1: 302

# ======= DATA を内部で設定
自作関数 <- function(x, y) {
    df <- data.frame(                  #    c1 c2
                  c1 = c(11, 12, 13),  # 1  11 21
                  c2 = c(21, 22, 23))  # 2  12 22
    z <- sum(x) + y
    return(z)
}
bf = apply(df, 2, 自作関数, 100)   # 100 を y=100 としてもよい
bf[1] + bf[2]         # c1: 302
bf["c1"] + bf["c2"]   # c1: 302