【问题标题】:Transform a nested list to dataframe将嵌套列表转换为数据框
【发布时间】:2020-06-22 06:01:57
【问题描述】:

我有一个项目列表,每个项目有两个项目,一个是列表,另一个是字符表达式 我们生成de列表

My_list <- list()
My_list$'product1' <- list()
My_list$'product1'$'sales' <- c(1,2,3)
My_list$'product1'$'model' <- "arima"
My_list$'product2'$'sales' <- c(4,5,6)
My_list$'product2'$'model' <- "prophet"

这是所需的输出形状

df1 <- data.frame(product=c("product1"),sales1 = 1, sales2 = 2, sales3 = 3)
df2 <- data.frame(product=c("product2"),sales1 = 4, sales2 = 5, sales3 = 6)
solution <- rbind (df1,df2)

我尝试过类似的方法

solution <- lapply(My_list, function(x) do.call(rbind, lapply(x, as.data.frame)))
solution <- do.call(rbind, Map(cbind, product = names(My_list), My_list))
```7

【问题讨论】:

    标签: r list dataframe rbind do.call


    【解决方案1】:

    在我看来是一种非常直观且易于维护的方法:

    data.frame(product=names(My_list), 
               do.call(rbind, lapply(My_list, FUN=function(x) unlist(x["sales"]))), row.names = NULL)
    
       product sales1 sales2 sales3
    1 product1      1      2      3
    2 product2      4      5      6
    

    它使用lapply 遍历列表列表并取消列出所有sales 条目(自动命名它们)。然后使用do.call 将向量一起rbinds。


    将模型名称添加到表中的快速方法是使用rapply,默认情况下不会列出结果(请参阅?rapply 和参数how

    data.frame(model=rapply(My_list, f=paste, classes="character"),
               product=names(My_list), 
               do.call(rbind, lapply(My_list, FUN=function(x) unlist(x["sales"]))), row.names = NULL)
    
        model  product sales1 sales2 sales3
    1   arima product1      1      2      3
    2 prophet product2      4      5      6
    

    【讨论】:

    • 如何将“模型”绑定到数据框?
    • 查看编辑。我在rapply 中包含了一个示例。它假定My_list 中唯一的character 类是模型名称。
    【解决方案2】:

    这是一个基于 R 的简单版本,

    as.data.frame(matrix(unlist(My_list), nrow = length(My_list), byrow = TRUE))
    #  V1 V2 V3      V4
    #1  1  2  3   arima
    #2  4  5  6 prophet
    

    您可以轻松地进行修改以适应您的预期输出(更改名称并将 V4 转换为 product1product2),即

    #save the data frame
    d1 <- as.data.frame(matrix(unlist(My_list), nrow = length(My_list), byrow = TRUE))
    #Set the column names
    d1 <- setNames(d1, c(paste0('sales', seq(ncol(d1) - 1)), 'Product'))
    #Change the variable under `Product`
    d1$Product <- paste0('Product', seq(nrow(d1)))
    
    d1
    #  sales1 sales2 sales3  Product
    #1      1      2      3 Product1
    #2      4      5      6 Product2
    

    【讨论】:

      【解决方案3】:

      您可以使用lapply 中的[[My_list 中获取第一项sales,您可以使用rbinddo.call 获得第一项sales。从结果中设置了colnames

      tt <- do.call(rbind, lapply(My_list, "[[", 1))
      #tt <- do.call(rbind, lapply(My_list, "[[", "sales")) #Alternative
      colnames(tt) <- paste0("sales",seq_len(ncol(tt)))
      tt
      #         sales1 sales2 sales3
      #product1      1      2      3
      #product2      4      5      6
      

      【讨论】:

        【解决方案4】:

        这是一个基本的 R 解决方案:

        # transpose and fetch the sales arguments putting them in a df
        sales <-t(do.call(cbind,
                lapply(My_list, function(x) data.frame(x[names(x)=="sales"]))))
        
        # rename the rows with products
        rownames(sales) <- names(My_list)
        
        # rename columns 
        colnames(sales) <- paste0("sales",c(1:ncol(sales)))
        sales
        
                 sales1 sales2 sales3
        product1      1      2      3
        product2      4      5      6
        

        如果您需要带有产品列的 data.frame:

        sales <- data.frame(sales)
        sales$product <- rownames(sales)
        rownames(sales) <- 1:nrow(sales)
        sales
          sales1 sales2 sales3  product
        1      1      2      3 product1
        2      4      5      6 product2
        

        【讨论】:

          【解决方案5】:

          基本 R 选项

          solution <- cbind(Product = names(My_list),
                            `names<-`(r <- as.data.frame(do.call(rbind,sapply(My_list, `[`,-2)),row.names = FALSE),
                                      paste0("Sale",seq(ncol(r)))))
          

          给了

          > solution
             Product Sale1 Sale2 Sale3
          1 product1     1     2     3
          2 product2     4     5     6
          

          【讨论】:

            【解决方案6】:

            这是一个data.table 解决方案。我在下面的代码中添加了解释和中间结果作为注释...

            library(data.table)
            #bind list, using name as id
            DT <- rbindlist( My_list, idcol = "product" )
            #     product sales   model
            # 1: product1     1   arima
            # 2: product1     2   arima
            # 3: product1     3   arima
            # 4: product2     4 prophet
            # 5: product2     5 prophet
            # 6: product2     6 prophet
            
            #create rowid's by product-group, used for casting in the next line
            DT[, row_id := rowid(product) ]
            #     product sales   model row_id
            # 1: product1     1   arima      1
            # 2: product1     2   arima      2
            # 3: product1     3   arima      3
            # 4: product2     4 prophet      1
            # 5: product2     5 prophet      2
            # 6: product2     6 prophet      3
            
            #cast to wide format
            dcast( DT, product ~ paste0( "sales", row_id ), value.var = "sales" )
            #     product sales1 sales2 sales3
            # 1: product1      1      2      3
            # 2: product2      4      5      6
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-02-18
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多