【问题标题】:Split a list column into multiple columns将列表列拆分为多个列
【发布时间】:2018-11-25 15:29:12
【问题描述】:

我有一个数据框,其中最后一列是一列列表。下面是它的外观:

Col1 | Col2 | ListCol
--------------------------
 na  |  na  | [obj1, obj2]
 na  |  na  | [obj1, obj2]
 na  |  na  | [obj1, obj2]

我想要的是

Col1 | Col2 | Col3  | Col4
--------------------------
 na  |  na  | obj1  | obj2
 na  |  na  | obj1  | obj2
 na  |  na  | obj1  | obj2

我知道所有列表都有相同数量的元素。

编辑:

ListCol 中的每个元素都是一个包含两个元素的列表。

【问题讨论】:

  • 这很大程度上取决于ListCol 的结构。如果它包含每一行的数据框或命名列表,则只需 tidyr::unnest 即可。如果是其他结构,您可能需要先重新排列。要获得更好的答案,请在您的示例数据上使用调用 dput 的结果进行编辑,以便我们可以重现确切的结构。
  • 你好。我试过 unnest 但它一直在做的是让对象分开,但在不同的行而不是列中。 ListCol 的每一行都是一个列表
  • 让它横向扩展而不是向下扩展的最简单方法是使每个列表元素成为 1 行数据框,例如使用df$ListCol <- lapply(df$ListCol, function(x) as.data.frame(t(x)))(如果您愿意,可以使用 dplyr 和 purrr),然后调用 unnest
  • 这是 alisatire 针对类似问题的解决方案:stackoverflow.com/questions/49889246/how-to-unnest-column-list 使用 invoke_map 和 tibble。还有其他几个解决方案:stackoverflow.com/questions/49689927/…

标签: r multiple-columns


【解决方案1】:

目前,tidyverse 的答案是:

library(dplyr)
library(tidyr)
data %>% unnest_wider(ListCol)

【讨论】:

    【解决方案2】:

    这是一种方法,使用unnesttidyr::spread...

    library(dplyr)
    library(tidyr)
    
    #example df
    df <- tibble(a=c(1, 2, 3), b=list(c(2, 3), c(4, 5), c(6, 7)))
    
    df %>% unnest(b) %>% 
           group_by(a) %>% 
           mutate(col=seq_along(a)) %>% #add a column indicator
           spread(key=col, value=b)
    
          a   `1`   `2`
      <dbl> <dbl> <dbl>
    1    1.    2.    3.
    2    2.    4.    5.
    3    3.    6.    7.
    

    【讨论】:

    • 在您的示例中,您只是在做cbind(df[1],do.call(rbind,df$b)) 甚至cbind(df[1],t(data.frame(df$b)))
    • @Onyambu,你不想为这篇文章写一个完整的答案吗?它帮助了我,也可以帮助其他人,但我第一次错过了。
    【解决方案3】:

    两个出色答案的比较

    此线程中有两个很棒的单行建议:

    (1)cbind(df[1], t(data.frame(df$b)))

    这是来自@Onyambu 使用base R。要得到这个答案,需要知道dataframe 是一个列表,需要一点创造力。

    (2)df %&gt;% unnest_wider(b)

    这是来自@iago 使用tidyverse。您需要额外的软件包并了解所有nest 动词,但可以认为它更具可读性。

    现在让我们比较一下性能

    library(dplyr)
    library(tidyr)
    library(purrr)
    library(microbenchmark)
    
    N <- 100
    df <- tibble(a = 1:N, b = map2(1:N, 1:N, c))
    
    tidy_foo <- function() suppressMessages(df %>% unnest_wider(b))
    base_foo <- function() cbind(df[1],t(data.frame(df$b))) %>% as_tibble # To be fair
      
    microbenchmark(tidy_foo(), base_foo())
    

    Unit: milliseconds
           expr      min        lq      mean    median       uq      max neval
     tidy_foo() 102.4388 108.27655 111.99571 109.39410 113.1377 194.2122   100
     base_foo()   4.5048   4.71365   5.41841   4.92275   5.2519  13.1042   100
    

    哎呀!

    base R 解决方案快 20 倍。

    【讨论】:

    • 使用我的真实数据和问题,我发现差异不大。我的 data.frame 有 100k 行,65 列,我正在取消嵌套一对变量。 tidyr 解决方案需要 12.5 秒,基础 R 解决方案需要 11 秒,因此基础 R 解决方案要快 1.14 倍。用户可能想要测试自己的数据。
    【解决方案4】:

    这是data.tablebase::unlist 的选项。

    library(data.table)
    
    DT <- data.table(a = list(1, 2, 3),
                                     b = list(list(1, 2),
                                                  list(2, 1),
                                                  list(1, 1)))
    
    for (i in 1:nrow(DT)) {
      set(
        DT,
        i = i,
        j = c('b1', 'b2'),
        value = unlist(DT[i][['b']], recursive = FALSE)
      )
    }
    DT
    

    这需要在每一行上都有一个 for 循环...不理想并且 非常data.table。 我想知道是否有某种方法可以避免首先创建列表列...

    【讨论】:

      【解决方案5】:

      @Alec data.table 提供tstrsplit 函数将一列拆分为多列。

      DT = data.table(x=c("A/B", "A", "B"), y=1:3)
      DT[]
      
      #     x y
      #1: A/B 1
      #2:   A 2
      #3:   B 3
      
      DT[, c("c1") := tstrsplit(x, "/", fixed=TRUE, keep=1L)][] # keep only first
      
      #     x y c1
      #1: A/B 1  A
      #2:   A 2  A
      #3:   B 3  B
      
      DT[, c("c1", "c2") := tstrsplit(x, "/", fixed=TRUE)][]
      
      #     x y c1   c2
      #1: A/B 1  A    B
      #2:   A 2  A <NA>
      #3:   B 3  B <NA>
      

      【讨论】:

        猜你喜欢
        • 2019-06-05
        • 1970-01-01
        • 2022-01-09
        • 2023-01-11
        • 2016-05-31
        • 2020-02-10
        • 2022-01-18
        相关资源
        最近更新 更多