tibble :: add_row для вложенных ошибок бросков tibble под tidyr 1.0.0 - PullRequest
3 голосов
/ 17 января 2020

В предыдущей версии tidyr мне удалось добавить строки во вложенный тиббл, используя tibble::add_row. После обновления до версии 1.0.0 я получаю следующую ошибку:

Ошибка: levels.vctrs_list_of() не поддерживается.

library(dplyr, warn.conflicts = FALSE)
library(tibble)
library(tidyr) # version 1.0.0

mtcars %>% 
  tidyr::nest(data = dplyr::select(., -cyl) %>% colnames) %>% 
  tibble::add_row(cyl = "all cyl", data = NA)
#> Error: `levels.vctrs_list_of()` not supported.

Создано в 2020-01 -17 с помощью пакета Представить (v0.3.0)

И вот тот же вызов с использованием tidyr 0.8.3

library(dplyr, warn.conflicts = FALSE)
library(tibble)
library(tidyr) # version 0.8.3

 mtcars %>% 
   tidyr::nest(-cyl) %>% 
   tibble::add_row(cyl = "all cyl", data = NA)
  #> # A tibble: 4 x 2
  #>   cyl     data              
  #>   <chr>   <list>            
  #> 1 6       <tibble [7 × 10]> 
  #> 2 4       <tibble [11 × 10]>
  #> 3 8       <tibble [14 × 10]>
  #> 4 all cyl <lgl [1]>

Создано в 2020-01-17 с помощью пакета Представить (v0.3.0)

Другие пользователи испытывают то же самое или это указано c для моей системной среды? Нужно ли обновлять другие пакеты для запуска? Есть ли обходной путь? Стоит ли открывать вопрос на Github?

Обновление: В комментариях кто-то предлагал обновить пакет vctrs. Но после обновления до последней версии 0.2.1 такая же ошибка все еще появляется.

background / context

Я должен уточнить, почему я хотел использовать add_row с data = NA на первом месте.

Мой оригинальный скрипт выглядел примерно так:

# tidyr version 0.8.3 add_row was working
iris %>% 
  tidyr::nest(-Species) %>% 
  tibble::add_row(Species = "All species", data = NA) %>% 
  mutate(data = purrr::modify_at(4, ~ as_tibble(select(iris, -Species)))

, который возвращал вложенный тиббл со всеми категориями, а также с общей категорией.

Под tidyr 1.0.0 my код выглядит следующим образом и выдает указанную ошибку:

# tidyr version 1.0.0 where add_row does not work
iris %>% 
  tidyr::nest(data = dplyr::select(., -Species) %>% colnames) %>% 
  tibble::add_row(Species = "All species", data = NA) %>% 
  mutate(data = purrr::modify_at(data, nrow(.), ~ as_tibble(select(iris, -Species))))

Поскольку add_row больше не работает под tidyr 1.0.0, следующая лучшая аналогичная альтернатива, как @IceCreamToucan, предложила bind_rows.

# tidyr version 1.0.0 alternative with dpylr::bind_rows
iris %>% 
  tidyr::nest(data = dplyr::select(., -Species) %>% colnames) %>% 
  dplyr::bind_rows(tibble(Species = "All species", data = NA)) %>% 
  mutate(data = purrr::modify_at(data, nrow(.), ~ as_tibble(select(iris, -Species))))

Однако, поскольку синтаксис tidyr::nest стал более многословным в версии 1.0.0, я попытался упростить код, и это, пожалуй, самый простой подход, который я должен был выбрать, начиная с:

# What I should have been doing in the first place
iris %>% 
  dplyr::bind_rows(mutate(iris, Species = "All species")) %>% 
  tidyr::nest(data = dplyr::select(., -Species) %>% colnames) 

Ответы [ 3 ]

3 голосов
/ 17 января 2020

Обходной путь должен использовать bind_rows. Похоже, bind_rows выдает предупреждение при добавлении в столбец списка, а add_row выдает ошибку.

mtcars %>% 
  tidyr::nest(data = dplyr::select(., -cyl) %>% colnames) %>% 
  mutate_at(vars(cyl), as.character) %>% 
  bind_rows(tibble(cyl = 'all cyl', data = NA))

# # A tibble: 4 x 2
#   cyl     data              
#   <chr>   <list>            
# 1 6       <tibble [7 x 10]> 
# 2 4       <tibble [11 x 10]>
# 3 8       <tibble [14 x 10]>
# 4 all cyl <NULL>
# Warning message:
# In bind_rows_(x, .id) :
#   Vectorizing 'vctrs_list_of' elements may not preserve their attributes
2 голосов
/ 18 января 2020

Следуя совету Акруна, я установил версию dplyr (а также tibble, tidyr, vctrs, tidyselect) devel, и похоже, что следующие официальные версии tidyverse решат эту проблему.

Прежде всего, в исходном сообщении об ошибке теперь указывается c, и ясно, что добавление строки без общего типа невозможно.

library(tidyverse)
iris %>% 
  tidyr::nest(data = dplyr::select(., -Species) %>% colnames) %>% 
  tibble::add_row(tibble(Species = "All species", data = NA))
#> Error: No common type for `..1$data` <list> and `..2$data` <logical>.

Создано в 2020-01-18 с помощью представьте пакет (v0.3.0)

Это поведение можно обойти, обернув NA в list(). Тогда мы могли бы использовать modify_at для замены list(NA) на исходный тиббл.

library(tidyverse)
iris %>% 
   tidyr::nest(data = dplyr::select(., -Species) %>% colnames) %>% 
   tibble::add_row(Species = "All species", data = list(NA)) %>% 
   mutate(data = modify_at(data, nrow(.), ~ as_tibble(select(iris, -Species))))
#>  A tibble: 4 x 2
#>   Species     data              
#>   <chr>       <list>            
#> 1 setosa      <tibble [50 × 4]> 
#> 2 versicolor  <tibble [50 × 4]> 
#> 3 virginica   <tibble [50 × 4]> 
#> 4 All species <tibble [150 × 4]>

Создано в 2020-01-18 пакетом prex (v0. 3.0)

Однако теперь также можно добавить tibbles в качестве аргумента данных с add_row, поместив их в список, как в list(as_tibble(select(iris, -Species))):

library(tidyverse)
iris %>% 
  tidyr::nest(data = dplyr::select(., -Species) %>% colnames) %>% 
  tibble::add_row(Species = "All species",
                  data = list(as_tibble(select(iris, -Species))))
    #>  A tibble: 4 x 2
    #>   Species     data              
    #>   <chr>       <list>            
    #> 1 setosa      <tibble [50 × 4]> 
    #> 2 versicolor  <tibble [50 × 4]> 
    #> 3 virginica   <tibble [50 × 4]> 
    #> 4 All species <tibble [150 × 4]>

Создано в 2020-01-18 пакетом представ (v0.3.0)

Тем не менее, этот подход еще более многословен, чем тот, который я придумал в качестве промежуточного решения, которое я буду использовать отныне:

iris %>% 
  dplyr::bind_rows(mutate(iris, Species = "All species")) %>% 
  tidyr::nest(data = dplyr::select(., -Species) %>% colnames) 
1 голос
/ 17 января 2020

Существует проблема типа, и если мы добавляем NA элементы в столбец list, попробуйте

library(dplyr)
library(tidyr)
mtcars %>% 
  tidyr::nest(data = dplyr::select(., -cyl) %>% colnames) %>% 
  mutate(cyl = as.character(cyl)) %>%
  dplyr::add_row(cyl = "all cyl", 
    data = list(as.tibble(setNames(as.list(rep(NA_real_, ncol(mtcars) - 1)), 
         setdiff(names(mtcars), 'cyl'))))) 
...