【问题标题】:Convert list to data frame while keeping list-element names将列表转换为数据框,同时保留列表元素名称
【发布时间】:2012-09-20 07:24:23
【问题描述】:

我有一个列表,其中元素名称是 ID 标签,并且包含一个带有数值的向量。它们的长度不等(!)。

我想将其转换为一个数据框,其中一列中有 ID,另一列中有数值。例如:

$`1`  
[1] 1 2   
$`2`  
[1] 1 2 3 
$`3`  
[1] 1   

收件人:

ID   Obs  
1    1  
1    2
2    1
2    2
2    3
3    1

【问题讨论】:

    标签: r list dataframe r-faq


    【解决方案1】:

    这是一种方法:

    ## your list
    ll <- list("1" = 1:2, "2" = 1:3, "3" = 1:2)
    ## convert to data.frame
    dl <- data.frame(ID = rep(names(ll), sapply(ll, length)),
                     Obs = unlist(ll))
    

    这给出了:

    > dl
       ID Obs
    11  1   1
    12  1   2
    21  2   1
    22  2   2
    23  2   3
    31  3   1
    32  3   2
    

    data.frame() 调用中的第一行只是将列表中的names() 重复所需次数的一些代码。第二行只是取消列出将其转换为向量的列表。

    【讨论】:

    • 我给了你正确的答案,因为你的方法最快:
      > system.time(melt(X))
      用户系统已过
      3.12 0.11 3.24
      > system.time(data.frame(ID = rep(names(X), sapply(X, length)), Obs = unlist(X)))
      用户系统经过
      0.08 0.00 0.07
    • 我似乎无法添加换行符,对不起:S
    【解决方案2】:

    使用reshape2melt,它们有一个方法melt.list

    .list <- list(`1` = 1:2, `2` = 1:3, `3` = 1:2)
    library(reshape2)
    melt(.list)
    ##   value L1
    ## 1     1  1
    ## 2     2  1
    ## 3     1  2
    ## 4     2  2
    ## 5     3  2
    ## 6     1  3
    ## 7     2  3
    

    【讨论】:

      【解决方案3】:

      stack-function 是已经发布的解决方案的一个很好但仍然缺少的替代方案:

      df <- stack(ll)[2:1]
      

      给出:

      > df
        ind values
      1   1      1
      2   1      2
      3   2      1
      4   2      2
      5   2      3
      6   3      1
      7   3      2
      

      同样使用setNames,您可以获得所需的确切格式:

      df <- setNames(stack(ll)[2:1], c('ID','Obs'))
      

      给出:

      > df
        ID Obs
      1  1   1
      2  1   2
      3  2   1
      4  2   2
      5  2   3
      6  3   1
      7  3   2
      

      使用过的数据:

      ll <- list("1" = 1:2, "2" = 1:3, "3" = 1:2)
      

      【讨论】:

        【解决方案4】:

        使用基函数的解决方案

        List <- list('1'=c(1,2), '2'= c(1,2,3), '3'=1)
        x <- unlist(List)  # as suggested by Gavin Simpson
        data.frame(ID=substr(names(x),1,1), Obs=x)
           ID Obs
        11  1   1
        12  1   2
        21  2   1
        22  2   2
        23  2   3
        3   3   1
        

        如果您希望 rownames 为 1,2,3,4,5,6,请尝试以下操作(使用 setNames):

        data.frame(ID=substr(names(x),1,1), Obs=setNames(x, NULL))
          ID Obs
        1  1   1
        2  1   2
        3  2   1
        4  2   2
        5  2   3
        6  3   1
        

        此解决方案仅在所有名称的长度相同时才有效,否则会失败,最好使用 Gavin 的解决方案。例如:

        List2 <- list('week1'=c(1,2), 'week2'= c(1,2,3), 'week3'=1)
        x <- unlist(List2)  
        data.frame(ID=substr(names(x),1,nchar(names(x)[1])-1), Obs=setNames(x, NULL))
        
            ID   Obs
        1 week1   1
        2 week1   2
        3 week2   1
        4 week2   2
        5 week2   3
        6 week3   1
        

        【讨论】:

        • 我认为你可以做到x &lt;- unlist(List),不是吗?
        • @Gavin Simpson 你是对的,现在我刚刚编辑了我的答案,包括你的评论。
        • 似乎当我取消列出它时,它会在元素名称中添加一个数字,导致脚本的其余部分因我的目的而失败:S
        • @Jilber 抱歉,但现在它将所有名称更改为“2”或“5”。元素名称是由 ID.Seasons.Week 组成的因素,例如2225.Winter.1,如果有帮助的话。我喜欢尽可能使用基本功能的角度,所以如果它也能工作就好了..
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-25
        • 2020-07-08
        • 1970-01-01
        相关资源
        最近更新 更多