R×purrr::lmap_if リストのリスト要素に対して指定した条件に該当したときに関数を適用する

R言語で、リストのリスト要素に対して指定した条件に該当したときに関数を適用する方法について解説します。ここではtidyverseパッケージに含まれているpurrrパッケージのlmap_if()を使用した方法についてお伝えします。

lmap_if()の概要

lmap_if()は、リストのリスト要素に対して指定した条件に該当したときに関数を適用するための関数です。lmap_if()は、map_if()と似ていますが、.x[[i]]をマッピングする代わりに、.x[i]をマッピングします。これにはいくつかの利点があります。

  • リストのみを受け取る関数を扱えるようになります。
  • .fがnames()のように、カプセル化されたリストの属性にアクセスできるようになります。
  • .fが、出力のサイズを変更することで、受け取ったリストよりも大きいリストまたは小さいリストを返すことができます。

lmap_if()の使い方


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

lmap_if()の引数

.x

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

.p

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

.f

長さ1のリストを受け取り、任意の長さのリストを返す関数を指定します。

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


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

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

else = NULL

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

lmap_if()の戻り値

.xに一致するリストまたはデータフレームを返します。長さは保証されません。

準備

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


library(tidyverse)

使用例

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

次は、3つのユーザー情報(user01, user02, user03)を持つリストを作成し、各要素名(user01, user02, user03)の末尾に「A」を追加し、nameを大文字に変換するコードです。
ただし、ageが40以上の場合にのみ適用されます。


list(user01 = list(id = 100, name = "satou", age = 30),
     user02 = list(id = 101, name = "suzuki", age = 40),
     user03 = list(id = 102, name = "takahashi", age = 50)) |>
  lmap_if(
    \(x) x$age >= 40,
    function(x) {
      names(x) <- paste0(names(x), "A")
      x[[1]]$name <- str_to_upper(x[[1]]$name)
      x
  })

$user01
$user01$id
[1] 100

$user01$name
[1] "satou"

$user01$age
[1] 30


$user02A
$user02A$id
[1] 101

$user02A$name
[1] "SUZUKI"

$user02A$age
[1] 40


$user03A
$user03A$id
[1] 102

$user03A$name
[1] "TAKAHASHI"

$user03A$age
[1] 50