5

I have the following data structure:

library(tibble)

my_tbl <-
  tibble::tribble(
                   ~col_x,   ~col_y,
                   "a",      list(1, 2, 3),
                   "b",      list(4, 5, 6),
                   "c",      list(7, 8, 9)
                   )

And I want to use tidyr::unnest_wider() to separate col_y to columns. The names for those new columns should be taken from animal_names vector:

animal_names <- c("dog", "cat", "zebra")

How can I utilize unnest_wider() to apply the names from animal_names, thereby avoiding the following naming warning:

library(tidyr)

my_tbl %>%  
  unnest_wider(col_y)
#> New names:
#> * `` -> ...1
#> * `` -> ...2
#> * `` -> ...3
#> New names:
#> * `` -> ...1
#> * `` -> ...2
#> * `` -> ...3
#> New names:
#> * `` -> ...1
#> * `` -> ...2
#> * `` -> ...3
#> # A tibble: 3 x 4
#>   col_x  ...1  ...2  ...3
#>   <chr> <dbl> <dbl> <dbl>
#> 1 a         1     2     3
#> 2 b         4     5     6
#> 3 c         7     8     9

desired output

## # A tibble: 3 x 4
##   col_x   dog   cat zebra
##   <chr> <dbl> <dbl> <dbl>
## 1 a         1     2     3
## 2 b         4     5     6
## 3 c         7     8     9

Please note that @akrun suggested to add names to the nested values before unnesting.

library(dplyr)
library(purrr)

my_tbl %>%
  mutate(across(col_y, ~map(., .f = ~set_names(.x, animal_names)))) %>%
  unnest_wider(col_y)
#> # A tibble: 3 x 4
#>   col_x   dog   cat zebra
#>   <chr> <dbl> <dbl> <dbl>
#> 1 a         1     2     3
#> 2 b         4     5     6
#> 3 c         7     8     9

However, this is a redundant and expensive operation when we deal with large datasets. Can't we just apply names through unnest_wider()'s names_repair argument?

Emman
  • 3,695
  • 2
  • 20
  • 44

2 Answers2

5

The names_repair needs the full column names in addition to the column unnested. So, we create a vector of names excluding the 'col_y' concatenated with 'animal_names' vector and use that in names_repair

library(dplyr)
library(tidyr)
nm1 <- c(setdiff(names(my_tbl), 'col_y'), animal_names)
my_tbl %>%  
  unnest_wider(col_y, names_repair = ~ nm1) %>%
  suppressMessages

-output

# A tibble: 3 × 4
  col_x   dog   cat zebra
  <chr> <dbl> <dbl> <dbl>
1 a         1     2     3
2 b         4     5     6
3 c         7     8     9
akrun
  • 874,273
  • 37
  • 540
  • 662
  • Thanks, so simple. But I still get the annoying warning message. Why is that? – Emman Nov 04 '21 at 20:49
  • @Emman you meant the `New names:`. I think the warning is triggered before the names_repair because the `list` column is not named – akrun Nov 04 '21 at 20:49
  • Oh, I really hoped that if I use `unnest_wider()` own arguments, the warning will not show. Do you have an idea how we could silent the warning? – Emman Nov 04 '21 at 20:51
  • 1
    @Emman you may wrap with `suppressMessages(my_tbl %>% unnest_wider(col_y, names_repair = ~ nm1))` – akrun Nov 04 '21 at 20:51
  • It is not a warning. It is a message so it can be silenced with `suppressMessages` – akrun Nov 04 '21 at 20:52
  • very nice! it can even be added to the pipe after `unnest_wider()` – Emman Nov 04 '21 at 20:53
  • @Emman yes, it can be added. – akrun Nov 04 '21 at 20:54
0

If you are annoyed by the message, you can use the argument names_sep (in recent version of tidyr, either 1.0 or 1.1), which will silent the message. Because you override the values with names_repair, you can set any arbitrary value to names_sep="".


author: mstigler date: 2022-03-04 output: "reprex::reprex_document" title: woody-kiwi_reprex.R

library(tidyr)

my_tbl <-
  tibble::tribble(
    ~col_x,   ~col_y,
    "a",      list(1, 2, 3),
    "b",      list(4, 5, 6),
    "c",      list(7, 8, 9))

animal_names <- c("dog", "cat", "zebra")
nm1 <- c(setdiff(names(my_tbl), 'col_y'), animal_names)
my_tbl |>
  unnest_wider(col_y, names_repair = ~ nm1, names_sep = "")
#> # A tibble: 3 × 4
#>   col_x   dog   cat zebra
#>   <chr> <dbl> <dbl> <dbl>
#> 1 a         1     2     3
#> 2 b         4     5     6
#> 3 c         7     8     9

Created on 2022-03-04 by the reprex package (v2.0.0)

Matifou
  • 7,968
  • 3
  • 47
  • 52