Concatenando data.frames

Como juntar os diversos arquivos .dbc do DATASUS em um data.frame; comparação de tempos de processamento e bibliotecas.

Mario O. de Menezes https://momenezes.github.io/tutorials
10-01-2020

Introdução

O DATASUS, braço tecnológico do Ministério da Saúde, disponibiliza uma vasta quantidade de informações sobre diversos aspectos do Serviço Unificado de Saúde (SUS). Muitos destes arquivos são disponibilizados em um formato dbc, que é um “compressed DBF”.

Estes arquivos são disponibilizados no site de FTP do DATASUS. Para fins deste pequeno experimento, todos os arquivos foram baixados e estão na máquina local.

O objetivo deste pequeno estudo é verificar os tempos gastos em cada etapa: leitura dos arquivos, filtros e seleção de variáveis, e a transformação em um data.frame para posterior manipulação.

Carregando as bibliotecas

Listando todos os arquivos das APACS no diretório

Todos os arquivos das APACs foram baixados do site FTP do DATASUS.

diretorio <- "~/datasets/datasus.gov.br/SIASUS/PA-LaudosDiversos/"

Selecionando 4 arquivos, 2 de cada estado, de Minas Gerais e Rio de Janeiro

PREF <- "PA"
# indique o estado ou "" para todos os estados
UF <- "(MG|RJ)" 
MESES <- "12"
ANO <- "(18|19)"
arquivos <- list.files(diretorio, paste0(PREF,UF,ANO,MESES,".*.dbc"))

Variáveis selecionadas

vars_to_keep = c("PA_CODUNI","PA_UFMUN","PA_TPUPS","PA_TIPPRE", "PA_CNPJCPF",  "PA_MVM","PA_CMP","PA_PROC_ID","PA_CNSMED","PA_MOTSAI","PA_OBITO","PA_CIDPRI", "PA_CIDSEC","PA_CIDCAS","PA_CATEND","PA_IDADE","PA_SEXO","PA_RACACOR","PA_MUNPCN", "PA_UFDIF","PA_MNDIF","PA_ETNIA")

Tempo de leitura dos arquivos (em segundos)

timeMGRJ4arqs <- system.time({f1 <- read.dbc(paste0(diretorio,arquivos[1])); 
f2 <- read.dbc(paste0(diretorio,arquivos[2])); 
f3 <- read.dbc(paste0(diretorio,arquivos[3])); 
f4 <- read.dbc(paste0(diretorio,arquivos[4]));})
timeMGRJ4arqs
   user  system elapsed 
269.552  33.556 303.112 

Montando uma lista de data.frames

Para estes 4 arquivos iniciais, vou fazer o processo de montar a lista e concatenar usando as duas bibliotecas data.table e dplyr para comparar o tempo nesta etapa.

Cada data.frame inicial é filtrado e as variáveis são selecionadas; são colocados em uma lista de data.frames para a concatenação posterior.

Usando o data.table

apacsdt <- list()
timeMGRJ4arqs_tolistdt <- system.time({
  # f1
  f1 <- setDT(f1)
  f1 <-
    f1[(PA_PROC_ID == "0204030030" |
          PA_PROC_ID == "0204030188") &
         PA_SEXO == "F", ..vars_to_keep]
  estado <- substr(arquivos[1], 3, 4)
  ano <- substr(arquivos[1], 5, 6)
  mes <- substr(arquivos[1], 7, 8)
  ano <- as.numeric(paste0("20", ano))
  f1[, `:=`(ESTADO = estado,
            ANO = ano,
            MES = mes)]
  apacsdt  <- append(apacsdt, list(f1))
  
  #f2
  f2 <- setDT(f2)
  f2 <-
    f2[(PA_PROC_ID == "0204030030" |
          PA_PROC_ID == "0204030188") &
         PA_SEXO == "F", ..vars_to_keep]
  estado <- substr(arquivos[2], 3, 4)
  ano <- substr(arquivos[2], 5, 6)
  mes <- substr(arquivos[2], 7, 8)
  ano <- as.numeric(paste0("20", ano))
  f2[, `:=`(ESTADO = estado,
            ANO = ano,
            MES = mes)]
  apacsdt  <- append(apacsdt, list(f2))
  
  # f3
  f3 <- setDT(f3)
  f3 <-
    f3[(PA_PROC_ID == "0204030030" |
          PA_PROC_ID == "0204030188") &
         PA_SEXO == "F", ..vars_to_keep]
  estado <- substr(arquivos[3], 3, 4)
  ano <- substr(arquivos[3], 5, 6)
  mes <- substr(arquivos[3], 7, 8)
  ano <- as.numeric(paste0("20", ano))
  f3[, `:=`(ESTADO = estado,
            ANO = ano,
            MES = mes)]
  apacsdt  <- append(apacsdt, list(f3))
  
  # f4
  f4 <- setDT(f4)
  f4 <-
    f4[(PA_PROC_ID == "0204030030" |
          PA_PROC_ID == "0204030188") &
         PA_SEXO == "F", ..vars_to_keep]
  estado <- substr(arquivos[4], 3, 4)
  ano <- substr(arquivos[4], 5, 6)
  mes <- substr(arquivos[4], 7, 8)
  ano <- as.numeric(paste0("20", ano))
  f4[, `:=`(ESTADO = estado,
            ANO = ano,
            MES = mes)]
  apacsdt  <- append(apacsdt, list(f4))
  
})
timeMGRJ4arqs_tolistdt
   user  system elapsed 
  4.820   0.040   0.807 

Usando o dplyr

apacs <- list()
timeMGRJ4arqs_tolistdplyr <- system.time({
  # f1
  f1 <- f1 %>% filter((PA_PROC_ID == "0204030030" |
          PA_PROC_ID == "0204030188") &
         PA_SEXO == "F") %>%
    select(vars_to_keep)
  estado <- substr(arquivos[1], 3, 4)
  ano <- substr(arquivos[1], 5, 6)
  mes <- substr(arquivos[1], 7, 8)
  ano <- as.numeric(paste0("20", ano))
  f1 <- f1 %>% mutate(ESTADO=estado,ANO=ano,MES=mes)
  apacs  <- append(apacs, list(f1))
  
  #f2
  f2 <- f2 %>% filter((PA_PROC_ID == "0204030030" |
          PA_PROC_ID == "0204030188") &
         PA_SEXO == "F") %>%
    select(vars_to_keep)
  estado <- substr(arquivos[2], 3, 4)
  ano <- substr(arquivos[2], 5, 6)
  mes <- substr(arquivos[2], 7, 8)
  ano <- as.numeric(paste0("20", ano))
  f2 <- f2  %>% mutate(ESTADO=estado,ANO=ano,MES=mes)
  apacs  <- append(apacs, list(f2))
  
  # f3
  f3 <- f3 %>% filter((PA_PROC_ID == "0204030030" |
          PA_PROC_ID == "0204030188") &
         PA_SEXO == "F") %>%
    select(vars_to_keep)
  estado <- substr(arquivos[3], 3, 4)
  ano <- substr(arquivos[3], 5, 6)
  mes <- substr(arquivos[3], 7, 8)
  ano <- as.numeric(paste0("20", ano))
  f3 <- f3 %>% mutate(ESTADO=estado,ANO=ano,MES=mes)
  apacs  <- append(apacs, list(f3))
  
  # f4
  f4 <- f4 %>% filter((PA_PROC_ID == "0204030030" |
          PA_PROC_ID == "0204030188") &
         PA_SEXO == "F") %>%
    select(vars_to_keep)
  estado <- substr(arquivos[4], 3, 4)
  ano <- substr(arquivos[4], 5, 6)
  mes <- substr(arquivos[4], 7, 8)
  ano <- as.numeric(paste0("20", ano))
  f4 <- f4 %>% mutate(ESTADO=estado,ANO=ano,MES=mes)
  apacs  <- append(apacs, list(f4))
  
})
timeMGRJ4arqs_tolistdplyr
   user  system elapsed 
  0.096   0.000   0.095 

Concatenando os data.frames

Com a função rbindlist do pacote data.table

timeMGRJ4arqs_todf <- system.time({
X <-
  data.table::rbindlist(apacsdt) 
assign("APACSPA_MGRJdt", X)
rm(X)
})
timeMGRJ4arqs_todf
   user  system elapsed 
  0.028   0.000   0.026 

Com a função bind_rows do pacote dplyr

timeMGRJ4arqs_tolistdplyr <- system.time({
  X <-
   bind_rows(apacs)
assign("APACSPA_MGRJdplyr", X)
rm(X)
})
timeMGRJ4arqs_tolistdplyr
   user  system elapsed 
  0.076   0.000   0.074 

Selecionando 4 arquivos de São Paulo

PREF <- "PA"
# indique o estado ou "" para todos os estados
UF <- "SP" 
MESES <- "(01|02)"
ANO <- "19"
arquivos <- list.files(diretorio, paste0(PREF,UF,ANO,MESES,".*.dbc"))

Tempo de leitura dos arquivos (em segundos)

timeSP4arqs <- system.time({f1 <- read.dbc(paste0(diretorio,arquivos[1])); 
f2 <- read.dbc(paste0(diretorio,arquivos[2])); 
f3 <- read.dbc(paste0(diretorio,arquivos[3])); 
f4 <- read.dbc(paste0(diretorio,arquivos[4]));})
timeSP4arqs
   user  system elapsed 
319.472  29.012 348.506 

Montando a lista de data.frames

apacs <- list()
timeSP4arqs_tolist <- system.time({
  # f1
  f1 <- setDT(f1)
  f1 <-
    f1[(PA_PROC_ID == "0204030030" |
          PA_PROC_ID == "0204030188") &
         PA_SEXO == "F", ..vars_to_keep]
  estado <- substr(arquivos[1], 3, 4)
  ano <- substr(arquivos[1], 5, 6)
  mes <- substr(arquivos[1], 7, 8)
  ano <- as.numeric(paste0("20", ano))
  f1[, `:=`(ESTADO = estado,
            ANO = ano,
            MES = mes)]
  apacs  <- append(apacs, list(f1))
  
  # f2
  f2 <- setDT(f2)
  f2 <-
    f2[(PA_PROC_ID == "0204030030" |
          PA_PROC_ID == "0204030188") &
         PA_SEXO == "F", ..vars_to_keep]
  estado <- substr(arquivos[2], 3, 4)
  ano <- substr(arquivos[2], 5, 6)
  mes <- substr(arquivos[2], 7, 8)
  ano <- as.numeric(paste0("20", ano))
  f2[, `:=`(ESTADO = estado,
            ANO = ano,
            MES = mes)]
  apacs  <- append(apacs, list(f2))
  
  # f3
  f3 <- setDT(f3)
  f3 <-
    f3[(PA_PROC_ID == "0204030030" |
          PA_PROC_ID == "0204030188") &
         PA_SEXO == "F", ..vars_to_keep]
  estado <- substr(arquivos[3], 3, 4)
  ano <- substr(arquivos[3], 5, 6)
  mes <- substr(arquivos[3], 7, 8)
  ano <- as.numeric(paste0("20", ano))
  f3[, `:=`(ESTADO = estado,
            ANO = ano,
            MES = mes)]
  apacs  <- append(apacs, list(f3))
  
  # f4
  f4 <- setDT(f4)
  f4 <-
    f4[(PA_PROC_ID == "0204030030" |
          PA_PROC_ID == "0204030188") &
         PA_SEXO == "F", ..vars_to_keep]
  estado <- substr(arquivos[4], 3, 4)
  ano <- substr(arquivos[4], 5, 6)
  mes <- substr(arquivos[4], 7, 8)
  ano <- as.numeric(paste0("20", ano))
  f4[, `:=`(ESTADO = estado,
            ANO = ano,
            MES = mes)]
  apacs  <- append(apacs, list(f4))
  
})
timeSP4arqs_tolist
   user  system elapsed 
  3.680   0.000   0.598 

Concatenando os data.frames

Com a função rbindlist do pacote data.table

timeSP4arqs_todf <- system.time({
X <-
  data.table::rbindlist(apacs)
assign("APACSPA_SPdt", X)
rm(X)
})
timeSP4arqs_todf
   user  system elapsed 
  0.040   0.000   0.038 

Com a função bind_rows do pacote dplyr

timeSP4arqs_tolistdplyr <- system.time({
  X <-
   bind_rows(apacs)
assign("APACSPA_SPdplyr", X)
rm(X)
})
timeSP4arqs_tolistdplyr
   user  system elapsed 
  0.096   0.000   0.096 

Gravando um CSV

Usando data.table - função fwrite

caminho <- getwd()
nomearquivocsv <- "APACSSPdt.CSV"
system.time(fwrite(APACSPA_SPdt,paste(caminho,nomearquivocsv,sep="/")))
   user  system elapsed 
  0.880   0.044   0.541 

Usando readr - função write_csv

nomearquivocsv <- "APACSSPdplyr.CSV"
system.time(write_csv(APACSPA_SPdt,paste(caminho,nomearquivocsv,sep="/")))
   user  system elapsed 
  0.636   0.752   1.301 

Reuse

Text and figures are licensed under Creative Commons Attribution CC BY 4.0. The figures that have been reused from other sources don't fall under this license and can be recognized by a note in their caption: "Figure from ...".

Citation

For attribution, please cite this work as

Menezes (2020, Oct. 1). Tips to Share and Grow: Concatenando data.frames. Retrieved from https://momenezes.github.io/tutorials/posts/2020-10-01-concatenando-dataframes/

BibTeX citation

@misc{menezes2020concatenando,
  author = {Menezes, Mario O. de},
  title = {Tips to Share and Grow: Concatenando data.frames},
  url = {https://momenezes.github.io/tutorials/posts/2020-10-01-concatenando-dataframes/},
  year = {2020}
}