Como salvar vários arquivos com write_rds() e purrr?

Olá!

Essa dúvida surgiu em uma aula no curso “R para Ciência de Dados I”

Contexto: utilizamos o código abaixo para carregar todos os arquivos neste link de uma vez. Cada arquivo representa um ano da base imdb.

arquivos <- list.files("dados/por_ano/", full.names = TRUE)
imdb <- purrr::map_dfr(arquivos, readr::read_rds)

A dúvida é : é possível usar a mesma lógica para salvar os arquivos (com write_rds())?

Caso seja necessário a base imdb completa, é possível carregá-la com o código abaixo:

imdb <- read_delim("https://raw.githubusercontent.com/curso-r/202010-r4ds-1/master/dados/imdb2.csv", ";", escape_double = FALSE, trim_ws = TRUE)

1 Curtida

beatrizmilz,

Acho que a chave para salvar o resultado de um dplyr::group_by() em vários arquivos é usar dplyr::group_split() e purrr::map(). Com certeza eu gastei mais tempo do que eu devia pensando em diversos jeitos de fazer isso, mas abaixo estão 5 maneiras de salvar agrupamentos de uma tabela em múltiplos arquivos :smiley:

library(magrittr)

# Ler os arquivos como na pergunta
arquivos <- list.files("dados/por_ano/", full.names = TRUE)
imdb <- purrr::map_dfr(arquivos, readr::read_rds)

# Criar o caminho final a partir de um ano
make_file <- function(year) {
  paste0("dados/por_ano/imdb_", year, ".rds")
}


# CAFÉ COM LEITE ---------------------------------------------------------

# Agrupar e quebrar a tabela pela variável
tmp <- imdb %>%
  dplyr::group_by(ano) %>%
  dplyr::group_split()

# Criar um vetor com os caminhos finais
caminhos <- purrr::map(tmp, ~make_file(.x$ano[1]))

# Fazer um map2() para usar as listas de tabelas e de caminhos
lixo <- purrr::map2(tmp, caminhos, readr::write_rds)


# FÁCIL ------------------------------------------------------------------

# Agrupar e quebrar a tabela pela variável
tmp <- imdb %>%
  dplyr::group_by(ano) %>%
  dplyr::group_split()

# Usar como nome de cada elemento o caminho do arquivo final
names(tmp) <- purrr::map(tmp, ~make_file(.x$ano[1]))

# Usar imap() para simplificar o trabalho
lixo <- purrr::imap(tmp, readr::write_rds)


# INTERMEDIÁRIO ----------------------------------------------------------

# Pipeline: criar uma coluna com caminhos, transpor e walk()
imdb %>%
  dplyr::group_by(ano) %>%
  dplyr::group_split() %>%
  dplyr::tibble(data = .) %>%
  dplyr::rowwise() %>%
  dplyr::mutate(file = make_file(data$ano[1])) %>%
  purrr::transpose() %>%
  purrr::walk(~readr::write_rds(.x$data, .x$file))


# DIFÍCIL ----------------------------------------------------------------

# Se você odeia o dplyr, dá para fazer tudo direto
imdb %>%
  dplyr::group_by(ano) %>%
  dplyr::group_split() %>%
  purrr::walk(~readr::write_rds(.x, make_file(.x$ano[1])))


# DIABÓLICO --------------------------------------------------------------

# Se você se odeia, dá para usar só purrr
imdb %>%
  purrr::map(unique(.$ano), ~imdb[imdb$ano == .x,], .) %>%
  purrr::walk(~readr::write_rds(.x, make_file(.x$ano[1])))

Created on 2020-10-15 by the reprex package (v0.3.0)

2 Curtidas

Qual pacote da função make_file?

tentei replicar deu erro
Error in make_file(.x$ano[1]) :
não foi possível encontrar a função “make_file”

Joel,

Eu crio ela no começo do código:

# Criar o caminho final a partir de um ano
make_file <- function(year) {
  paste0("dados/por_ano/imdb_", year, ".rds")
}

Verdade… boa…

vai ser util isso rsrsrs