29.20 Simplifying list-columns

To simplify the list-column back to a regular column (an atomic vector) or set of columns:

  1. If you want a single value, use mutate() with map_lgl(), map_int(), map_dbl(), and map_chr() to create an atomic vector.
  2. If you want many values, use unnest() to convert list-columns back to regular columns, repeating the rows as many times as necessary.

29.20.1 List to vector

You can always summarise an object with its type and length, so this code will work regardless of what sort of list-column you have.

df <- tribble(
  ~x,
  letters[1:5],
  1:3,
  runif(5)
)

df %>% mutate(
  type = map_chr(x, typeof),
  length = map_int(x, length)
)

Although being the same basic information you get from the default tbl print method, you can now use if for filtering.

Don’t forget about the map_*() shortcuts - you can use map_chr(x, "apple") to extract the string stored in apple for each element of x.

Use the .null argument to provide a value to use if the element is missing (instead of returning NULL).

df <- tribble(
  ~x,
  list(a = 1, b = 2),
  list(a = 2, c = 4)
)
df %>% mutate(
  a = map_dbl(x, "a"),
  b = map_dbl(x, "b", .null = NA_real_)
)

29.20.2 Unnesting

unnest() works by repeating the regular columns once for each element of the list-column.

tibble(x = 1:2, y = list(1:4, 1)) %>% unnest(y)

You cannot simultaneously unnest two columns that contain different number of elements.

# Ok, because y and z have the same number of elements in
# every row
df1 <- tribble(
  ~x, ~y,           ~z,
   1, c("a", "b"), 1:2,
   2, "c",           3
)
df1
df1 %>% unnest(c(y, z))

# Doesn't work because y and z have different number of elements
df2 <- tribble(
  ~x, ~y,           ~z,
   1, "a",         1:2,  
   2, c("b", "c"),   3
)
df2

df2 %>% unnest(c(y, z))