rfsaldanha / microdatasus

Download de dados do DataSUS e pré-processamento no R.
https://rfsaldanha.github.io/microdatasus/
Other
228 stars 55 forks source link

Melhorar eficiencia da função process_cnes() #74

Closed rafapereirabr closed 1 year ago

rafapereirabr commented 1 year ago

Oi Rafael. Notei que a função process_cnes() está toda escrita em base R, o que deixa o codigo bem lento, especial no caso de bases com muitas observações. Eu vetorizei várias operações e traduzi o script para sintaxe do data.tabe, de maneira que o script ficou beeem mais eficiente.

Num teste rápido aqui para uma base pequena (um mês de "CNES-PF" de Roraima), a função atual demora cerca de 15 segundos, e a versão com data.table demora cerca de 1 segundo. Para bases maiores, essa diferença tende a ser ainda maior.

Boa parte das alterações que fiz poderiam ser aproveitadas para melhorar as demais funções process_ sem muito esforço.

Se você tiver interesse, eu posso detalhar melhor essa comparação acima, e fazer um pull request. Sei que manutenção de pacote dá um baita trabalho e tem suas idiosincrasias. Então fique a vontade para recusar a sugestão ou responder quando puder.

rfsaldanha commented 1 year ago

Olá Rafael,

Perfeito! Tenho vontade de refatorar todo o pacote, usando dplyr ou dtplyr (que usa internamente o data.table), para deixar o código melhor, mais bem escrito e mais eficiente.

O tempo está curto para fazer isso agora, mas toda ajuda é bem-vinda.

rafapereirabr commented 1 year ago

opa. Aqui um report mais detalhado dos resutlados da minha implementação em data.table da função process_cnes():

data download

utils::remove.packages('microdatasus')
devtools::install_github("rfsaldanha/microdatasus")
library(microdatasus)
library(tictoc)

cnes_st_cran <- fetch_datasus(year_start = 2016,
                              month_start = 6,
                              year_end = 2016,
                              month_end = 6, uf = "AC",
                              information_system = "CNES-ST")

cnes_pf_cran <- fetch_datasus(year_start = 2016,
                              month_start = 6,
                              year_end = 2016,
                              month_end = 6,
                              uf = "AC",
                              information_system = "CNES-PF")

Current package

tic()
proc_st_cran <- process_cnes(
  data = cnes_st_cran,
  information_system = "CNES-ST",
  nomes = TRUE,
  municipality_data = TRUE
)
toc()
#> 1.95 sec elapsed

tic()
proc_pf_cran <- process_cnes(
  data = cnes_pf_cran,
  information_system = "CNES-PF",
  nomes = TRUE,
  municipality_data = TRUE
)
toc()
#> 14.6 sec elapsed

Dev version

utils::remove.packages('microdatasus')
devtools::install_github("rafapereirabr/microdatasus")
library(microdatasus)
library(tictoc)

tic()
proc_st_dev <- process_cnes(
  data = cnes_st_cran,
  information_system = "CNES-ST",
  nomes = TRUE,
  municipality_data = TRUE
)
toc()
#> 2.71 sec elapsed

tic()
proc_pf_dev <- process_cnes(
  data = cnes_pf_cran,
  information_system = "CNES-PF",
  nomes = TRUE,
  municipality_data = TRUE
)
toc()
#> 0.49 sec elapsed

check result

# estabelecimentos
identical(proc_st_cran, proc_st_dev)
#> FALSE

# pessoas fisicas
identical(proc_pf_cran, proc_pf_dev)
#> TRUE

Os outputs são diferentes apenas para a base de estabelecimentos. No entanto, diferença está em 3 variáveis c("ATEND_PR", "TP_PREST", "NAT_JUR"). Ao que parece, o código original não estava processando a recodificação dessas variáveis corretamente. A versão data.table corrige isso, e por isso dá a impressão de que ela é mais lenta, mas na verdade ela está processando mais dados.

Com esse código abaixo dá para ter uma bom diagnóstico de comparação dos outputs.

library(arsenal)
summary(arsenal::comparedf(proc_st_cran, proc_st_dev))

toma seu tempo e veja o que acha. Se quiser, eu posso abrir um pull request.

rafapereirabr commented 1 year ago

outro ponto é que eu reduzi muito a redundância do código. O script original tinha quase 1800 linhas. A versão revisada com data.table tem 564 linhas. Para isso eu precisei criar algumas funções internas do pacote para conversao das classes das colunas.

rfsaldanha commented 1 year ago

Cara, isso é fantástico! Se já estiver maduro, faz um pull request e podemos fazer refatoração começando pelo CNES. Depois, vou refatorando as outras funções aprendendo com a sua. Muito obrigado!

rfsaldanha commented 1 year ago

Olá Rafael, aprovei o pull request agora. Obrigado!

rafapereirabr commented 1 year ago

otimo! valeu !