将列表中的所有名称保存到data.frame

时间:2016-12-18 17:33:46

标签: r list dataframe

将列表转换为data.frame时,R通过连接所有子列表名称自动命名变量。但是,当列表长度为1时,它似乎只保留姓氏。有没有办法为变量名强制执行完整路径名?

MWE:

> l <- list(a = list(b = 1), c = 2)
> l
$a
$a$b
[1] 1
$c
[1] 2

> data.frame(l)
  b c
1 1 2

> ll <- list(a = list(b = 1, bb = 1), c = 2)
> data.frame(ll)
  a.b a.bb c
1   1    1 2

在此,我希望将a.b作为data.frame(l)变量的名称,就像data.frame(ll)一样。

1 个答案:

答案 0 :(得分:2)

一种可能的解决方案是创建一个函数,将列表转换为as.data.frame()的数据框,然后在第二步中将名称设置为所需的值:

list_df <- function(list) {
  df <- as.data.frame(list)
  names(df) <- list_names(list)
  return (df)
}

显然,定义list_names()是困难的部分。一种可能性是通过嵌套列表递归:

list_names <- function(list) {

  recursor <- function(list, names) {
    if (is.list(list)) {
      new_names <- paste(names, names(list), sep = ".")
      out <- unlist(mapply(list, new_names, FUN = recursor))
    } else {
      out <- names
    }
    return(out)
  }

  new_names <- unlist(mapply(list, names(list), FUN = recursor))
  return(new_names)
}

这适用于您的两个例子:

l <- list(a = list(b = 1), c = 2)
ll <- list(a = list(b = 1, bb = 1), c = 2)
list_df(l)
##   a.b c
## 1   1 2
list_df(ll)
##   a.b a.bb c
## 1   1    1 2

它也适用于非嵌套的列表,以及具有更深嵌套的列表:

ls <- list(a = 1, b = 3)
lc <- list(a = list(b = 1, bb = 1), c = 2, d = list(e = list(f = 1, ff = 2), ee = list(fff = 5)))
list_df(ls)
##   a b
## 1 1 3
list_df(lc)
##   a.b a.bb c d.e.f d.e.ff d.ee.fff
## 1   1    1 2     1      2        5