cucumber flesh

Rを中心としたデータ分析・統計解析らへんの話題をしていくだけ

【小ネタ】リストにNULLがある場合のpurrr::map系関数の挙動

タイトルが適切かわからないが、小ネタ。次のようなリストオブジェクトがあるとする。リストに含まれる要素はname, age, genderの値をもっているが、2番目の要素はgenderがない、というようなもの。

library(purrr)
x <- list(list(name = "A", age = 23L, gender = "Male"), 
    list(name = "B", age = 18L), list(name = "C", 
        age = 24L, gender = "Male"))

これをpurrrを使って処理する。全ての要素に含まれるname, agemap系の関数で参照できる。一方でgenderについては、要素の数が合わないためにエラーになる。

x %>% map("name")
## [[1]]
## [1] "A"
## 
## [[2]]
## [1] "B"
## 
## [[3]]
## [1] "C"
x %>% map_int("age")
## [1] 23 18 24
x %>% map_chr("gender")
# Error: Result 2 is not a length 1
# atomic vector

このような場合の処置として、map関数では.nullという引数を用意していて、NA_integer_を指定すると足りない値を欠損値として扱ってくれる。

x %>% map_chr("gender", .null = NA_integer_)
## [1] "Male" NA     "Male"

ニュースを見ると、どうやら0.2.1からの仕様らしい。それに関する議論もある。

また返り値をデータフレーム化するmap_df()では、要素数が一致しなくても、.nullを指定しなくても、欠損値として処理される。AIEEEEEE!!??

x %>% map_df(~.)
## # A tibble: 3 x 3
##    name   age gender
##   <chr> <int>  <chr>
## 1     A    23   Male
## 2     B    18   <NA>
## 3     C    24   Male

mapを利用する別の関数でも.nullが指定可能である。

x %>% at_depth(1, "gender", .null = NA_integer_) %>% 
    flatten_chr()
## [1] "Male" NA     "Male"