R×purrr::accumulate リストまたはベクトルの要素を累積計算して中間結果を含むベクトルを取得する

R言語で、リストまたはベクトルの要素を累積計算して中間結果を含むベクトルを取得する方法について解説します。ここではtidyverseパッケージに含まれているpurrrパッケージのaccumulate()を使用した方法についてお伝えします。

accumulate()の概要

accumulate()は、リストまたはベクトルの要素を累積計算して中間結果を含むベクトルを取得するための関数です。accumulate()は、2つの引数を持つ関数をベクトルの要素に順次適用します。関数の各適用では、最初の引数として初期値または前回の適用結果を使用します。2番目の引数はベクトルの次の値です。各適用の結果はリストで返されます。累積は、ベクトル全体の処理を実行する前に、accumulate()関数から返されるdone()シグナルに応じて終了することもできます。

accumulate()の使い方


accumulate(
  .x,
  .f,
  ...,
  .init,
  .dir = c("forward", "backward"),
  .simplify = NA,
  .ptype = NULL
)

accumulate2(.x, .y, .f, ..., .init, .simplify = NA, .ptype = NULL)

accumulate()の引数

.x

リストまたはベクトルを指定します。

.f

accumulate()の場合、.fは2つの引数を持つ関数です。この関数には、第1引数として累積結果または初期値が渡されます。第2引数として、シーケンス内の次の値が渡されます。
accumulate2()の場合、3つの引数を持つ関数です。この関数には、第1引数として累積結果が渡されます。第2引数として、.x のシーケンス内の次の値が渡されます。第3引数として、.y のシーケンス内の次の値が渡されます。
.fがdone()でラップされた値を返す場合、累積は早期に終了します。

マッピングされた関数に渡される追加の引数を指定します。
.fに追加の(定数)引数を渡すために…を使用することは、現在では一般的に推奨されていません。代わりに、省略形の匿名関数を使用してください。
例えば、次のように書きます。


# 代わりに
x |> map(f, 1, 2, collapse = ",")
# 次のようにします。
x |> map(\(x) f(x, 1, 2, collapse = ","))

これにより、どの引数がどの関数に属しているかを理解しやすくなり、エラーメッセージもわかりやすくなります。

.init

指定されている場合、.x[[1]]ではなく、累積を開始する最初の値として使用されます。これは、.xが空の場合にreduceが正しい値を返すことを保証したい場合に便利です。指定されていない場合、.xが空であればエラーが発生します。

.dir = c(“forward”, “backward”)

蓄積方向を表す文字列を指定します。
「forward」(デフォルト)または「backward」のいずれかを指定します。

.simplify = NA

NA(デフォルト)の場合、累積された結果リストは、可能な場合はアトミックベクトルに簡略化されます。TRUEの場合、結果は簡略化され、不可能な場合はエラーが返されます。FALSEの場合、結果は簡略化されず、常にリストが返されます。

.ptype = NULL

simplifyがNAまたはTRUEの場合、オプションでベクトルプロトタイプを指定して出力タイプを強制します。

.y

.yは、accumulate2()のペアの2番目の引数です。これは、累積するベクトル(.x)より1要素短い必要があります。.init が設定されている場合、.yは初期値と.xを連結したものより1要素短い必要があります。

準備

あらかじめ、tidyverseパッケージを読み込んでおきます。


library(tidyverse)

使用例

5つの文字「a」「b」「c」「d」「e」を順次「-」で結合して、中間結果を含めてベクトルで取得するには次のようにします。


accumulate(letters[1:5], ~ paste(..1, ..2, sep = "-"))

[1] "a"         "a-b"       "a-b-c"     "a-b-c-d"   "a-b-c-d-e"