将列表列拆分为R中的多个列

San*_*nti 5 r multiple-columns

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

Col1 | Col2 | ListCol
--------------------------
 na  |  na  | [obj1, obj2]
 na  |  na  | [obj1, obj2]
 na  |  na  | [obj1, obj2]
Run Code Online (Sandbox Code Playgroud)

我想要的是

Col1 | Col2 | Col3  | Col4
--------------------------
 na  |  na  | obj1  | obj2
 na  |  na  | obj1  | obj2
 na  |  na  | obj1  | obj2
Run Code Online (Sandbox Code Playgroud)

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

编辑:

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

iag*_*ago 9

目前,tidyverse 的答案是:

library(dplyr)
library(tidyr)
data %>% unnest_wider(ListCol)
Run Code Online (Sandbox Code Playgroud)

  • 如果您需要保留嵌套列的名称,您还可以添加 `names_sep` 参数(例如 `data %>% unnest_wider(ListCol, names_sep="_")` 将导致 `ListCol_Col3`,这在取消嵌套时很方便一次多列)。 (2认同)

And*_*tar 7

这是一种方法,使用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.
Run Code Online (Sandbox Code Playgroud)

  • 在你的例子中,你只是在做 `cbind(df[1],do.call(rbind,df$b))` 甚至 `cbind(df[1],t(data.frame(df$b)))` (4认同)

pie*_*ito 5

两个精彩答案的比较

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

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

这是@Onyambu使用base R 的结果。为了得到这个答案,我们需要知道 adataframe是一个列表,并且需要一点创造力。

(2)df %>% 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())
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)

哎哟!

base R解决方案快 20 倍。

  • 使用我的现实世界数据和问题,我发现差异较小。我的 data.frame 有 100k 行、65 列,并且我取消嵌套一对变量。tidyr 解决方案需要 12.5 秒,基础 R 解决方案需要 11 秒,因此基础 R 解决方案快 1.14 倍。用户可能想测试自己的数据。 (3认同)