LoginSignup
0
0

More than 5 years have passed since last update.

オブジェクト名を生かしたlistを作る

Last updated at Posted at 2018-09-30

オブジェクトからリストを作成すると、オブジェクトの名前は失われてしまいます。

a <- 1:3
b <- 11:13
c <- 21:23
list(a, b, c)
output
[[1]]
[1] 1 2 3

[[2]]
[1] 11 12 13

[[3]]
[1] 21 22 23

名前付きのリストにしたければ、list(a = a, b = b, c = c)のようにやるわけですが、オブジェクト名を2回書く必要があり、あまりスマートではありません。

ところがリストの特殊な形であるデータフレームを作成する関数data.frameでは、明示的に名前を指定しなければ列名としてオブジェクト名が設定されます。

df <- data.frame(a, b, c)
as.list(df)
output
$a
[1] 1 2 3

$b
[1] 11 12 13

$c
[1] 21 22 23

ということは、何かやり方があるはずです。

単純にやるなら、オブジェクトの名前を取得して、リストの名前にセットしてやれば良いので、例えば次のような関数を定義します。

namedlist1 <- function(...){
  setNames(list(...), eval(substitute(alist(...))))
}
namedlist1(a, b, c)
output
$a
[1] 1 2 3

$b
[1] 11 12 13

$c
[1] 21 22 23

eval(substitute(alist(...)))の部分は、rlangパッケージを使ってもう少し簡潔に書くこともできます。

namedlist2 <- function(...){
  setNames(list(...), rlang::exprs(...))
}

しかし、この場合は明示的に名前を指定した場合にもオブジェクトの名前が優先して使われてしまいます。

namedlist1(a, hoge = b, c)
output
$a
[1] 1 2 3

$b
[1] 11 12 13

$c
[1] 21 22 23

リストの2つめの要素は名前がhogeになってほしいところでした。

ところでこの「明示的に名前を指定した場合にはその名前を使う」という動作もdata.frameだと実現できています。

as.list(data.frame(a, hoge = b, c))
output
$a
[1] 1 2 3

$hoge
[1] 11 12 13

$c
[1] 21 22 23

上記のようにdata.frameas.list()でリストに変換する方法は、いつでも使えるわけではありません。data.frameには要素数が等しいという制約があるためです。

しかしdata.frameは実際これをやっているわけですから、中身を覗いてそこだけ拝借すれば同じことができるのではないでしょうか?

やってみました。

namedlist3 <- function(...){
  object_name <- as.character(eval(substitute(alist(...))))
  x <- list(...)
  vnames <- names(x)
  novnames <- !nzchar(vnames)
  if (length(novnames) > 0L){
    vnames[novnames] <- object_name[novnames]
  } else {
    vnames <- object_name
  }
  setNames(x, vnames)
}
namedlist3(a, hoge = b, c)
output
$a
[1] 1 2 3

$hoge
[1] 11 12 13

$c
[1] 21 22 23

できました。

要するに名前が設定されていない部分を探してオブジェクト名をセットしているだけなのですが、data.frameの中ではこういう地道なことが行われていたのでした。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0