I have this dataset:
col1 col2
a c(1,2)
b 5
I want this dataset:
col1 col2_1 col2_2 col2_5
a TRUE TRUE FALSE
b FALSE FALSE TRUE
I know I have to use pivot wider. But I don't know how! Would you please help?
CodePudding user response:
You could unnest col2
and then reshape data to wide.
library(tidyr)
df %>%
unnest(col2) %>%
pivot_wider(col1, names_from = col2, names_prefix = "col2_",
values_from = col2, values_fn = Negate(is.na), values_fill = FALSE)
# # A tibble: 2 × 4
# col1 col2_1 col2_2 col2_5
# <chr> <lgl> <lgl> <lgl>
# 1 a TRUE TRUE FALSE
# 2 b FALSE FALSE TRUE
Data
df <- data.frame(col1 = c('a', 'b'))
df$col2 <- list(1:2, 5)
# col1 col2
# 1 a 1, 2
# 2 b 5
CodePudding user response:
Using tabulate
.
f <- \(x) {
m <- max(unlist(x))
t <- t(sapply(x, tabulate, m))
`mode<-`(t, 'logical')
}
cbind(dat[1], col2=f(dat$col2))
# col1 col2.1 col2.2 col2.3 col2.4 col2.5
# 1 a TRUE TRUE FALSE FALSE FALSE
# 2 b FALSE FALSE FALSE FALSE TRUE
To get the subset:
cbind(dat[1], col2=f(dat$col2)) |>
{\(.) subset(., select=c(1, which(apply(.[-1], 2, any)) 1))}()
# col1 col2.1 col2.2 col2.5
# 1 a TRUE TRUE FALSE
# 2 b FALSE FALSE TRUE
--
Data:
dat <- list2DF(list(c('a', 'b'), list(c(1, 2), 5))) |> setNames(paste0('col', 1:2))
CodePudding user response:
We could use mtabulate
library(qdapTools)
out <- cbind(df1, mtabulate(df1$col2) > 0)
names(out)[-(1:2)] <- paste0('col2_', names(out)[-(1:2)])
-output
> out
col1 col2 col2_1 col2_2 col2_5
1 a 1, 2 TRUE TRUE FALSE
2 b 5 FALSE FALSE TRUE
data
df1 <- structure(list(col1 = c("a", "b"), col2 = list(1:2, 5)),
row.names = c(NA,
-2L), class = "data.frame")