[英]Split a list column into multiple columns
I have a data table where the last column is a column of lists.我有一个数据表,其中最后一列是一列列表。 Below is how it looks:
下面是它的外观:
Col1 | Col2 | ListCol
--------------------------
na | na | [obj1, obj2]
na | na | [obj1, obj2]
na | na | [obj1, obj2]
What I want is我想要的是
Col1 | Col2 | Col3 | Col4
--------------------------
na | na | obj1 | obj2
na | na | obj1 | obj2
na | na | obj1 | obj2
I know that all the lists have the same amount of elements.我知道所有列表都具有相同数量的元素。
Edit:编辑:
Every element in ListCol is a list with two elements. ListCol 中的每个元素都是一个包含两个元素的列表。
Here is one approach, using unnest
and tidyr::spread
...这是一种方法,使用
unnest
和tidyr::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.
Currently, the tidyverse answer would be:目前,tidyverse 的答案是:
library(dplyr)
library(tidyr)
data %>% unnest_wider(ListCol)
There are two great one liner suggestions in this thread:该线程中有两个很棒的单行建议:
cbind(df[1], t(data.frame(df$b)))
cbind(df[1], t(data.frame(df$b)))
This is from @Onyambu
using base
R .这是来自
@Onyambu
使用base
R 。 To get to this answer one needs to know that a dataframe
is a list and needs a bit of creativity.要得到这个答案,需要知道
dataframe
是一个列表,需要一点创造力。
df %>% unnest_wider(b)
df %>% unnest_wider(b)
This is from @iago
using tidyverse
.这是来自
@iago
使用tidyverse
。 You need extra packages and to know all the nest
verbs, but one can think that it is more readable.您需要额外的包并了解所有
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 solution is 20 times faster. base
R解决方案快 20 倍。
Here's an option with data.table
and base::unlist
.这是一个带有
data.table
和base::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
This requires a for loop on every row... Not ideal and very anti- data.table
.这需要在每一行上都有一个 for 循环......不理想并且非常反对
data.table
。 I wonder if there's some way to avoid creating the list column in the first place...我想知道是否有某种方法可以避免首先创建列表列...
@Alec data.table
offers tstrsplit
function to split a column into multiple columns. @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>
I have a data table where the last column is a column of lists.我有一个数据表,其中最后一列是列表的一列。 Below is how it looks:
下面是它的外观:
Col1 | Col2 | ListCol
--------------------------
na | na | [obj1, obj2]
na | na | [obj1, obj2]
na | na | [obj1, obj2]
What I want is我想要的是
Col1 | Col2 | Col3 | Col4
--------------------------
na | na | obj1 | obj2
na | na | obj1 | obj2
na | na | obj1 | obj2
I know that all the lists have the same amount of elements.我知道所有列表都有相同数量的元素。
Edit:编辑:
Every element in ListCol is a list with two elements. ListCol中的每个元素都是一个包含两个元素的列表。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.