Dados Faltantes

Como identificar, remover ou imputar valores de dados faltantes.

Jose Storopoli https://scholar.google.com/citations?user=xGU7H1QAAAAJ&hl=en (UNINOVE)https://www.uninove.br , Leonardo Vils https://scholar.google.com/citations?user=VO07L9EAAAAJ&hl=en (UNINOVE)https://www.uninove.br
January 11, 2021

Dados faltantes são um problema comum em qualquer análise de dados.

O que são dados faltantes?

Os valores ausentes podem ser de três tipos gerais (Kang, 2013; Rubin, 1976):

  1. Totalmente ausente de maneira aleatória (missing completely at random – MCAR): Quando os dados ausentes são MCAR, a presença / ausência de dados é completamente independente das variáveis observáveis e dos parâmetros de interesse. Nesse caso, as análises realizadas nos dados são imparciais. Na prática, é altamente improvável. Pode haver perda de potência das técnicas estatísticas, mas os parâmetros estimados não são influenciados pela ausência de dados.
  2. Ausente de maneira aleatória (missing at random – MAR): Quando os dados ausentes não são aleatórios, mas podem ser totalmente relacionados a uma variável onde há informações completas. Um exemplo1 é que os homens têm menos probabilidade de preencher uma pesquisa sobre depressão, mas isso não tem nada a ver com seu nível de depressão, após levar em conta a masculinidade. Esse tipo de dados ausentes pode induzir um viés em sua análise, especialmente se desequilibrar seus dados por causa de muitos valores ausentes em uma determinada categoria.
  3. Ausente de maneira não-aleatória (missing not at random – MNAR): Quando os valores ausentes não são MCAR nem MAR. No exemplo anterior, esse seria o caso se as pessoas tendessem a não responder à pesquisa dependendo de seu nível de depressão. Os casos de dados MNAR são problemáticos. A única maneira de obter uma estimativa imparcial dos parâmetros em tal caso é modelar os dados ausentes2. O modelo pode então ser incorporado em um mais complexo para estimar os valores ausentes.

Como testar para dados faltantes?

Um teste muito usado é o Teste de MCAR de Little (R. J. A. Little, 1988) que possui como hipótese nula “os dados faltantes são totalmente ausentes de maneira aleatória (MCAR)”. Ou seja, um \(p\)-valor pequeno (\(p < 0.05\)) é geralmente interpretado como evidências contrárias que os dados são MCAR. O teste é baseado em um teste de chi-quadrado sobre frequências esperadas vs frequências observadas.

A biblioteca {naniar} (Tierney, Cook, McBain, & Fay, 2020) possui a função mcar_test() que implementa o teste de MCAR de Little. Além disso, possui diversas outras funcionalidades para sumarizar, visualizar e manipular com dados faltantes. Caso queira incorporar na sua análise recomendamos ler o manual da biblioteca.

O que fazer com dados faltantes?

O melhor método possível de lidar com os dados ausentes é evitar o problema planejando bem o estudo e coletando os dados cuidadosamente. Caso isso não seja possível, temos duas abordagens básicas para lidar com dados faltantes:

  1. remover os dados faltantes.
  2. imputar valores nos dados faltantes.

Remover dados faltantes

A remoção de dados faltantes se divide em duas principais abordagens usando a função na.omit() padrão do R:

  1. remoção de observações com dados faltantes: aqui removemos as linhas com dados faltantes df <- na.omit(df).
  2. remoção de variáveis com dados faltantes: aqui removemos as colunas com dados faltantes df <- t(na.omit(t(df))).

Imputar valores nos dados faltantes

“The idea of imputation is both seductive and dangerous” (R. J. Little & Rubin, 2019)

A imputação de dados é um método aplicado para imputar um valor para cada item ausente. De acordo com R. J. Little & Rubin (2019), imputações de dados simples podem ser definidas como médias ou extrações de uma distribuição preditiva de valores ausentes, requerem um método de criação de uma distribuição preditiva para imputação com base nos dados observados e definem duas abordagens genéricas para gerar tal distribuição preditiva: modelagem explícita e modelagem implícita.

Na modelagem explícita, a distribuição preditiva é baseada em um modelo estatístico formal, por exemplo, normal multivariado, portanto, as suposições são explícitas. Exemplos de modelagem explícita são imputação de média, imputação de regressão, imputação de regressão estocástica.

Na modelagem implícita3, o foco está em um algoritmo, o que implica um modelo subjacente. Suposições estão implícitas, mas ainda precisam ser avaliadas com cuidado para garantir que sejam razoáveis.

Dentre as diversas maneiras de imputar valores ao dados faltantes, as mais comuns são três:

  1. imputar a média.
  2. imputar a mediana.
  3. imputar o último valor ocorrido (last observation carried forward – LOFC): muito usada em séries temporais.

Mas ainda há maneiras mais avançadas e que desempenham melhor em certas condições (não cobriremos essas técnicas aqui):

  1. Imputação por \(k\)-vizinhos mais próximos (\(k\)-nearest neighbors imputation) (Troyanskaya et al., 2001).
  2. Imputação por florestas aleatórias (random forest imputation) (Pantanowitz & Marwala, 2009).

A biblioteca DescTools(Andri et mult. al., 2020) é uma coleção de funções focadas especialmente na parte descritiva de análise de um dataset. Inclusive a função Impute() – imputar valores em dados faltates usando qualquer função do R – e a função LOCF() que permite imputar o último valor ocorrido.

Para mostrar as abordagens, geramos um dataset de uma série temporal de uma semana com dados faltantes:

library(DescTools)
set.seed(123)
df <- data.frame(
  dia = c("seg", "ter", "qua", "qui", "sex", "sab", "dom"),
  valor = runif(7))
indices_aleatorios <- sample(1:nrow(df), 2)
df[indices_aleatorios[1], 2] <- NA
df[indices_aleatorios[2], 2] <- NA

Teste MCAR de Little

# A tibble: 1 x 4
  statistic    df p.value missing.patterns
      <dbl> <dbl>   <dbl>            <int>
1     0.700     1   0.403                2

O teste retornou um \(p\)-valor de 0.4027837, e não conseguimos rejeitar a \(H_0\) de que “os dados faltantes são totalmente ausentes de maneira aleatória (MCAR).” Notem que o nosso dataset possui apenas 7 observações e por isso o teste não possui poder o suficiente para rejeitar a hipótese nula caso ela seja falsa.

Imputar a média

df$media <- Impute(df$valor, FUN = mean(df$valor, na.rm = TRUE))

Imputar a mediana

df$mediana <- Impute(df$valor, FUN = median(df$valor, na.rm = TRUE))

Imputar o último valor ocorrido – LOCF

df$LOCF <- LOCF(df$valor)

Comparação dos resultados

library(skimr)
library(gt)
df %>% gt() %>% tab_header("Dados Faltantes usando as diferentes Técnicas de Imputação")
Dados Faltantes usando as diferentes Técnicas de Imputação
dia valor media mediana LOCF
seg 0.2875775 0.2875775 0.2875775 0.2875775
ter 0.7883051 0.7883051 0.7883051 0.7883051
qua NA 0.6854946 0.7883051 0.7883051
qui 0.8830174 0.8830174 0.8830174 0.8830174
sex 0.9404673 0.9404673 0.9404673 0.9404673
sab NA 0.6854946 0.7883051 0.9404673
dom 0.5281055 0.5281055 0.5281055 0.5281055
skim(df)
Table 1: Data summary
Name df
Number of rows 7
Number of columns 5
_______________________
Column type frequency:
character 1
numeric 4
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
dia 0 1 3 3 0 7 0

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
valor 2 0.71 0.69 0.27 0.29 0.53 0.79 0.88 0.94 ▃▃▁▃▇
media 0 1.00 0.69 0.22 0.29 0.61 0.69 0.84 0.94 ▂▂▁▇▅
mediana 0 1.00 0.71 0.23 0.29 0.66 0.79 0.84 0.94 ▂▂▁▇▅
LOCF 0 1.00 0.74 0.24 0.29 0.66 0.79 0.91 0.94 ▂▂▁▅▇

Ambiente

R version 4.0.3 (2020-10-10)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Catalina 10.15.7

Matrix products: default
BLAS:   /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRblas.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods  
[7] base     

other attached packages:
 [1] naniar_0.6.0.9000    purrr_0.3.4          gtsummary_1.3.6     
 [4] gt_0.2.2             lm.beta_1.5-1        lmtest_0.9-38       
 [7] zoo_1.8-8            ggfortify_0.4.11     sjPlot_2.8.7        
[10] broom_0.7.4          palmerpenguins_0.1.0 magrittr_2.0.1      
[13] mnormt_2.0.2         cowplot_1.1.1        tidyr_1.1.2         
[16] DescTools_0.99.40    skimr_2.1.2          ggpubr_0.4.0        
[19] car_3.0-10           carData_3.0-4        patchwork_1.1.1     
[22] dplyr_1.0.4          ggplot2_3.3.3        DiagrammeR_1.0.6.1  
[25] readxl_1.3.1        

loaded via a namespace (and not attached):
  [1] backports_1.2.1     repr_1.1.3          splines_4.0.3      
  [4] usethis_2.0.1       digest_0.6.27       htmltools_0.5.1.1  
  [7] magick_2.6.0        fansi_0.4.2         checkmate_2.0.0    
 [10] openxlsx_4.2.3      modelr_0.1.8        colorspace_2.0-0   
 [13] haven_2.3.1         xfun_0.21           crayon_1.4.1       
 [16] jsonlite_1.7.2      Exact_2.1           lme4_1.1-26        
 [19] survival_3.2-7      glue_1.4.2          gtable_0.3.0       
 [22] emmeans_1.5.4       sjstats_0.18.1      sjmisc_2.8.6       
 [25] abind_1.4-5         scales_1.1.1        mvtnorm_1.1-1      
 [28] DBI_1.1.1           rstatix_0.6.0       ggeffects_1.0.1    
 [31] Rcpp_1.0.6          xtable_1.8-4        performance_0.7.0  
 [34] tmvnsim_1.0-2       reticulate_1.18     foreign_0.8-80     
 [37] htmlwidgets_1.5.3   RColorBrewer_1.1-2  ellipsis_0.3.1     
 [40] pkgconfig_2.0.3     farver_2.0.3        sass_0.3.1         
 [43] utf8_1.1.4          tidyselect_1.1.0    labeling_0.4.2     
 [46] rlang_0.4.10        effectsize_0.4.3    munsell_0.5.0      
 [49] cellranger_1.1.0    tools_4.0.3         visNetwork_2.0.9   
 [52] cli_2.3.0           generics_0.1.0      sjlabelled_1.1.7   
 [55] evaluate_0.14       stringr_1.4.0       yaml_2.2.1         
 [58] fs_1.5.0            knitr_1.31          zip_2.1.1          
 [61] visdat_0.5.3        rootSolve_1.8.2.1   nlme_3.1-149       
 [64] xml2_1.3.2          compiler_4.0.3      rstudioapi_0.13    
 [67] curl_4.3            e1071_1.7-4         ggsignif_0.6.0     
 [70] tibble_3.0.6        statmod_1.4.35      broom.helpers_1.1.0
 [73] stringi_1.5.3       highr_0.8           parameters_0.11.0  
 [76] forcats_0.5.1       lattice_0.20-41     Matrix_1.2-18      
 [79] commonmark_1.7      nloptr_1.2.2.2      ggsci_2.9          
 [82] vctrs_0.3.6         norm_1.0-9.5        pillar_1.4.7       
 [85] lifecycle_0.2.0     estimability_1.3    data.table_1.13.6  
 [88] insight_0.12.0      lmom_2.8            R6_2.5.0           
 [91] bookdown_0.21       gridExtra_2.3       rio_0.5.16         
 [94] gld_2.6.2           distill_1.2         boot_1.3-25        
 [97] MASS_7.3-53         assertthat_0.2.1    rprojroot_2.0.2    
[100] withr_2.4.1         mgcv_1.8-33         bayestestR_0.8.2   
[103] expm_0.999-6        hms_1.0.0           grid_4.0.3         
[106] class_7.3-17        minqa_1.2.4         rmarkdown_2.6      
[109] downlit_0.2.1       lubridate_1.7.9.2   base64enc_0.1-3    
Andri et mult. al., S. (2020). DescTools: Tools for descriptive statistics. Retrieved from https://cran.r-project.org/package=DescTools
Kang, H. (2013). The prevention and handling of the missing data. Korean Journal of Anesthesiology, 64(5), 402.
Little, R. J. A. (1988). A test of missing completely at random for multivariate data with missing values. Journal of the American Statistical Association, 83(404), 1198–1202. https://doi.org/10.1080/01621459.1988.10478722
Little, R. J., & Rubin, D. B. (2019). Statistical analysis with missing data (Vol. 793). John Wiley & Sons.
Obadia, Y. (2017). The use of KNN for missing values. Retrieved from https://towardsdatascience.com/the-use-of-knn-for-missing-values-cf33d935c637
Pantanowitz, A., & Marwala, T. (2009). Missing data imputation through the use of the random forest algorithm. In W. Yu & E. N. Sanchez (Eds.), Advances in computational intelligence (pp. 53–62). Berlin, Heidelberg: Springer Berlin Heidelberg.
Rubin, D. B. (1976). Inference and missing data. Biometrika, 63(3), 581–592.
Tierney, N., Cook, D., McBain, M., & Fay, C. (2020). Naniar: Data structures, summaries, and visualisations for missing data. Retrieved from https://CRAN.R-project.org/package=naniar
Troyanskaya, O., Cantor, M., Sherlock, G., Brown, P., Hastie, T., Tibshirani, R., … Altman, R. B. (2001). Missing value estimation methods for DNA microarrays. Bioinformatics, 17(6), 520–525.

  1. adaptado de Obadia (2017)↩︎

  2. algo que não será demonstrado aqui. Recomendamos um livro-texto seminal de R. J. Little & Rubin (2019)↩︎

  3. não abordaremos essas técnicas↩︎

References

Corrections

If you see mistakes or want to suggest changes, please create an issue on the source repository.

Reuse

Text and figures are licensed under Creative Commons Attribution CC BY-SA 4.0. Source code is available at https://github.com/storopoli/Estatistica, unless otherwise noted. 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

Storopoli & Vils (2021, Jan. 11). Estatística com R: Dados Faltantes. Retrieved from https://storopoli.github.io/Estatistica/aux-Dados_Faltantes.html

BibTeX citation

@misc{storopoli2021dadosfaltantesR,
  author = {Storopoli, Jose and Vils, Leonardo},
  title = {Estatística com R: Dados Faltantes},
  url = {https://storopoli.github.io/Estatistica/aux-Dados_Faltantes.html},
  year = {2021}
}