fishdata
fishdata

Reputation: 113

Un-nesting lists within a tibble list column

I have a tibble with a list column where each element contains a list of length 2. I have tried to use unlist(), unnest() and flatten() and various other combinations but no luck getting my desired outcome.

A minimal working example is below:

df <- tibble(x = c('A', 'B'),
         preds = list(list(Phi = data.frame(time = 1:2, estimate = c('y1', 'y2')),
                           p = data.frame(time = 1:2, estimate = c('y3', 'y4'))),
                      list(Phi = data.frame(time = 1:2, estimate = c('y5', 'y6')),
                           p = data.frame(time = 1:2, estimate = c('y7', 'y8')))))

with an expected outcome:

output <- tibble(x = rep(c('A', 'B'), each = 4),
             grp = c(rep(c('Phi', 'p'), each = 2 ), rep(c('Phi', 'p'), each = 2 )),
             time = rep(1:2, 4),
             estimate = c('y1', 'y2', 'y3', 'y4', 'y5', 'y6', 'y7', 'y8'))

The following code gets me part way and I could easily include the other columns, but its not correct.

df$preds %>% flatten_df()

After a day of googling I'm still stuck. Please point me in some direction.......many thanks!!!

Upvotes: 2

Views: 545

Answers (1)

Kevin Arseneau
Kevin Arseneau

Reputation: 6264

Building on akrun's already good answer, I offer the following.

library(tidyr)
library(dplyr)

df %>%
  mutate(
    preds = lapply(
      preds, lapply, mutate, estimate = as.character(estimate)
    ) %>%
    lapply(bind_rows, .id = "grp")
  ) %>%
  unnest

# # A tibble: 8 x 4
#       x   grp  time estimate
#   <chr> <chr> <int>    <chr>
# 1     A   Phi     1       y1
# 2     A   Phi     2       y2
# 3     A     p     1       y3
# 4     A     p     2       y4
# 5     B   Phi     1       y5
# 6     B   Phi     2       y6
# 7     B     p     1       y7
# 8     B     p     2       y8

N.B. The only improvement is the conversion of estimate from factor to character. Otherwise, and if this could be addressed in the source data, the map solution by akrun is more concise and easier to reason about.

Upvotes: 1

Related Questions