【问题标题】:column names when using `as.data.frame` over nested list在嵌套列表上使用“as.data.frame”时的列名
【发布时间】:2020-09-15 18:48:01
【问题描述】:

假设我们有一个嵌套列表lst,如下所示

lst <- list(
  A = list(a.x = 1:5, a.y = 6:10),
  B = list(b.x = -(1:5), b.y = -(6:10), b.z = -(11:15))
)

> lst
$A
$A$a.x
[1] 1 2 3 4 5

$A$a.y
[1]  6  7  8  9 10


$B
$B$b.x
[1] -1 -2 -3 -4 -5

$B$b.y
[1]  -6  -7  -8  -9 -10

$B$b.z
[1] -11 -12 -13 -14 -15

当我使用df &lt;- as.data.frame(lst) 时,我们得到

> df
  A.a.x A.a.y B.b.x B.b.y B.b.z
1     1     6    -1    -6   -11
2     2     7    -2    -7   -12
3     3     8    -3    -8   -13
4     4     9    -4    -9   -14
5     5    10    -5   -10   -15

如您所见,lst 的不同层的名称由. 连接以生成列名称,例如A.a.x。由于我在lst的更深层已经有了.,例如a.x,所以A.a.x这样的列名看起来有点混乱。

我想知道. 是否是使用as.data.frame 而不是list 时的默认连接符号。否则,是否有任何可选参数允许用户在使用as.data.frame 时定义自己的符号(而不是.)?

【问题讨论】:

  • 可能与make.namesas.data.frame中被调用有关,后者调用make.unique,make.unique为function (names, sep = ".")
  • @akrun 感谢您的评论!似乎make.names 影响行名而不是​​列名。你有解决这个问题的办法吗?
  • 如果您查看as.data.frame.list 源代码,这似乎发生在最后一行do.call(data.frame,然后您可能已经查看了data.frame 源代码。有几个地方,调用make.unique
  • Thomas,正如@akrun 所说,如果您通过跟踪代码,我们会来到data.frame,尽管问题不在于make.namesmake.unique。如果您有一个嵌套列表传递给data.frame,您将转到else paste(vnames[[i]], namesi, sep = ".") 行(这是函数体的第67 行)。这需要一个已经从嵌套向量创建的数据框,并将父元素的名称粘贴到其列名上。所以不幸的是,这被硬编码为data.frame。您最好的选择是您自己的自定义命名包装器。
  • @AllanCameron 谢谢,现在我知道那里发生了什么。

标签: r list dataframe


【解决方案1】:

更改名称的行是 line no: 68 in data.frame

paste(vnames[[i]], namesi, sep = ".")

如果我们使用一些print 语句,它就会变得清晰。由于sep是硬编码的,所以只有更改函数的body才能更改

do.call(f2, lst)
#[1] "before change"
#[1] "A"
#[1] "A"
#[1] "after change"
#[1] "A.a.x" "A.a.y"
#[1] "before change"
#[1] "B"
#[1] "B"
#[1] "after change"
#[1] "B.b.x" "B.b.y" "B.b.z"

其中 'f2' 是带有 print 语句的更改函数

【讨论】:

    【解决方案2】:

    作为 akrun 出色答案的后续,这里有一个简单的包装器,您可以使用它来指定分隔符:

    as_data_frame <- function(lst, sep = ".")
    {
       setNames(as.data.frame(lst),
       unlist(mapply(function(x, y) paste(x, y, sep = sep), 
                     names(lst), lapply(lst, names))))
    }
    

    所以你可以拥有:

    as_data_frame(lst, "->")
    #>   A->a.x A->a.y B->b.x B->b.y B->b.z
    #> 1      1      6     -1     -6    -11
    #> 2      2      7     -2     -7    -12
    #> 3      3      8     -3     -8    -13
    #> 4      4      9     -4     -9    -14
    #> 5      5     10     -5    -10    -15
    

    【讨论】:

      猜你喜欢
      • 2016-05-14
      • 1970-01-01
      • 2016-06-04
      • 2021-10-30
      • 1970-01-01
      • 1970-01-01
      • 2013-08-07
      相关资源
      最近更新 更多