R×purrr::map_if ベクトルの要素に条件付きで関数を適用しリストを返す

R言語で、ベクトルの要素に条件付きで関数を適用しリストを返す方法について解説します。ここではtidyverseパッケージに含まれているpurrrパッケージのmap_if()を使用した方法についてお伝えします。

map_if()の概要

map_f()は、ベクトルの要素に条件付きで関数を適用しリストを返すための関数です。map_if()は、入力として述語関数.pを受け取り、.xのどの要素を.fで変換するかを決定します。

map_if()の使い方


map_if(.x, .p, .f, ..., .else = NULL)

map_if()の引数

.x

リストまたはデータフレームを指定します。

.p

単一の述語関数、そのような述語関数を記述する式、または.x と同じ長さの論理ベクトルを指定します。
または、.xの要素自体がオブジェクトのリストである場合は、内部リスト内の論理要素の名前を示す文字列を指定します。
.pがTRUEと評価される要素のみが変更されます。

.f

関数を指定します。
以下のいずれかの方法で指定されます。

  • 名前付き関数(例:mean)。
  • 匿名関数(例:\(x) x + 1 または function(x) x + 1)。
  • 数式(例:~ .x + 1)。最初の引数を参照するには.xを使用する必要があります。現在は推奨されていません。
  • 文字列、整数、またはリスト(例:”idx”, 1、list(“idx”, 1))。これらはそれぞれ \(x) pluck(x, “idx”)、\(x) pluck(x, 1)、\(x) pluck(x, “idx”, 1) の省略形です。インデックス付き要素がNULLまたは存在しない場合にデフォルト値を設定するには、オプションで.defaultを指定します。

【実験的】
関数をin_parallel()で囲むことで、その関数を並列実行するように指定できます。詳しくはin_parallel()を参照してください。このコンテキストでは「…」の使用は許可されていません。

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


# 次の代わりに
x |> map(f, 1, 2, collapse = ",")
# 次のように実行してください。
x |> map(\(x) f(x, 1, 2, collapse = ","))

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

else = NULL

.pがFALSEを返す.xの要素に適用される関数を指定します。

map_if()の戻り値

入力と同じ長さのリストを返します。

使用例

準備

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


library(tidyverse)

リストの要素名と値を同時に変更する

次は、ベクトルの要素が偶数ならば、その数値を10倍してリストで返すというコードです。


c(1, 12, 123) |>
  map_if(
    \(x) x %% 2 == 0,
    \(x) x * 10)

[[1]]
[1] 1

[[2]]
[1] 120

[[3]]
[1] 123