Pré-processamento de dados

Imputação de dados numéricos ausentes (missing data)

Antonio Sergio da Silva

Criado no RStudio Version 1.3.1073, R Version 4.0.2


## Carregando pacotes exigidos: pacman

Nota explicativa sobre os pacotes carregados.

pacman: for loading/unloading packages (package management tool).

magrittr: for a forwarding pipe operator.

rio: for importing data.

tidyverse: import, tidy, transform, visualize, and model data.

readxl: for reading excel files.

openxlsx: does not require rJava package.

writexl: for exporting excel files.

sampling: for generating samples.

knitr/xtable/stargazer: for generating tabels on RMarkdown.

mice: for visualizing data

visdat: for visualizing data

naniar: for visualizing and working with missing data

simputation: for simple imputation (for handling missing values and converting them into values)


Objetivos

  • Verificar missing data do tipo numérico.

  • Tratar missing data do tipo numérico.

    • Deletar todas as observações com atributos ausentes.

    • Imputar valores nas células vazias com a média ou a mediana.

    • Imputar valores ausente com regressão linear.

    • Imputar valores ausentes com random forest.


Importar Banco de Dados Ilustrativo

##      id idade estatura peso        imc renda  QI
## 1  1010    18     1.71   58  19.835163  5500  NA
## 2  1271    34     1.79   65  20.286508   750  NA
## 3  1308    44     1.66   94  34.112353  2500 110
## 4  1905    49     1.77   57  18.194006    NA 103
## 5  1916    19     1.75   82  26.775510  1500  NA
## 6  2628    35     1.64   79  29.372397  8500 107
## 7  2864    24     1.61   81  31.248794  6000 105
## 8  2886    46     <NA>   69  24.158818  4500  91
## 9  3504    35     1.79   58  18.101807  6000  98
## 10 3797    33     1.64   52 193.337299  3500 104
## 11 4047    25     1.69   NA  25.559329  5500 106
## 12 4334    39     1.64   85  31.603212  2000  95
## 13 4557    21      161   NA  29.705644    NA 107
## 14 4839    23     1.68   80  28.344671  9000 100
## 15 5041    26     1.79   64  19.974408  5500 108
## 16 6402    29     <NA>   58  21.303949 35000  92
## 17 7776    48     1.65   NA  27.915519  5500 110
## 18 8999    24     1.75   66   2.155102  4500  97
## 19 9200    28     1.74   56  18.496499    NA  94
## 20 9694    21     1.62   80  30.483158  1500  99

Visualização de Dados Ausentes

imput_num_visual <- imput_num %>%
  as_tibble ()
imput_num_visual
## # A tibble: 20 x 7
##       id idade estatura  peso    imc renda    QI
##    <dbl> <dbl> <chr>    <dbl>  <dbl> <dbl> <dbl>
##  1  1010    18 1.71        58  19.8   5500    NA
##  2  1271    34 1.79        65  20.3    750    NA
##  3  1308    44 1.66        94  34.1   2500   110
##  4  1905    49 1.77        57  18.2     NA   103
##  5  1916    19 1.75        82  26.8   1500    NA
##  6  2628    35 1.64        79  29.4   8500   107
##  7  2864    24 1.61        81  31.2   6000   105
##  8  2886    46 <NA>        69  24.2   4500    91
##  9  3504    35 1.79        58  18.1   6000    98
## 10  3797    33 1.64        52 193.    3500   104
## 11  4047    25 1.69        NA  25.6   5500   106
## 12  4334    39 1.64        85  31.6   2000    95
## 13  4557    21 161         NA  29.7     NA   107
## 14  4839    23 1.68        80  28.3   9000   100
## 15  5041    26 1.79        64  20.0   5500   108
## 16  6402    29 <NA>        58  21.3  35000    92
## 17  7776    48 1.65        NA  27.9   5500   110
## 18  8999    24 1.75        66   2.16  4500    97
## 19  9200    28 1.74        56  18.5     NA    94
## 20  9694    21 1.62        80  30.5   1500    99
# vis_dat() ---------- Retorna o dataset com as colunas em análise. Fornece uma visualização dos diferentes tipos de dados, inclusive dados ausentes. 

imput_num_visual %>% vis_dat()

# vis_miss() --------- Retorna uma visualização dos dados.

imput_num_visual %>% vis_miss()

# gg_miss_upset() ------- Retorna uma interação entre os dados selecionados.

imput_num_visual %>% gg_miss_upset()

# geom_miss_point() ----- Destaca os dados ausentes.

imput_num_visual %>%
  ggplot(aes(x = estatura, y = QI))+
  geom_miss_point()

Verificar dados ausentes (missing data)

sum(is.na(imput_num))
## [1] 11
colSums(is.na(imput_num))
##       id    idade estatura     peso      imc    renda       QI 
##        0        0        2        3        0        3        3
str(imput_num)
## 'data.frame':    20 obs. of  7 variables:
##  $ id      : num  1010 1271 1308 1905 1916 ...
##  $ idade   : num  18 34 44 49 19 35 24 46 35 33 ...
##  $ estatura: chr  "1.71" "1.79" "1.66" "1.77" ...
##  $ peso    : num  58 65 94 57 82 79 81 69 58 52 ...
##  $ imc     : num  19.8 20.3 34.1 18.2 26.8 ...
##  $ renda   : num  5500 750 2500 NA 1500 8500 6000 4500 6000 3500 ...
##  $ QI      : num  NA NA 110 103 NA 107 105 91 98 104 ...

A função md.patterndo pacote mice é uma alternativa para uma apresentação visual dos dados ausentes.

md.pattern(imput_num)

##    id idade imc estatura peso renda QI   
## 10  1     1   1        1    1     1  1  0
## 3   1     1   1        1    1     1  0  1
## 2   1     1   1        1    1     0  1  1
## 2   1     1   1        1    0     1  1  1
## 1   1     1   1        1    0     0  1  2
## 2   1     1   1        0    1     1  1  1
##     0     0   0        2    3     3  3 11

Transformar tipos de atributo.

imput_num[, 1] <- as.character(imput_num[,1])

imput_num[, 3] <- as.numeric(imput_num[,3])

str(imput_num)
## 'data.frame':    20 obs. of  7 variables:
##  $ id      : chr  "1010" "1271" "1308" "1905" ...
##  $ idade   : num  18 34 44 49 19 35 24 46 35 33 ...
##  $ estatura: num  1.71 1.79 1.66 1.77 1.75 1.64 1.61 NA 1.79 1.64 ...
##  $ peso    : num  58 65 94 57 82 79 81 69 58 52 ...
##  $ imc     : num  19.8 20.3 34.1 18.2 26.8 ...
##  $ renda   : num  5500 750 2500 NA 1500 8500 6000 4500 6000 3500 ...
##  $ QI      : num  NA NA 110 103 NA 107 105 91 98 104 ...

Cracterizar tipos de atributo.


Valores ausentes Valores inconsistentes Valores ruidosos Redundância de dados
Sim Sim Sim Sim

Cat Binário Cat Nominal Cat Ordinal Num Discreto Num Contínuo
- - - Idade Estatura
- - - Peso Renda
- - - QI -

Listar as observações (rows) com dados ausentes.

missing_data <- imput_num[!complete.cases(imput_num),]

missing_data
##      id idade estatura peso      imc renda  QI
## 1  1010    18     1.71   58 19.83516  5500  NA
## 2  1271    34     1.79   65 20.28651   750  NA
## 4  1905    49     1.77   57 18.19401    NA 103
## 5  1916    19     1.75   82 26.77551  1500  NA
## 8  2886    46       NA   69 24.15882  4500  91
## 11 4047    25     1.69   NA 25.55933  5500 106
## 13 4557    21   161.00   NA 29.70564    NA 107
## 16 6402    29       NA   58 21.30395 35000  92
## 17 7776    48     1.65   NA 27.91552  5500 110
## 19 9200    28     1.74   56 18.49650    NA  94
sum(is.na(missing_data))
## [1] 11

LDD1 - Ignorar as observações com dados ausentes

clean_data <- na.omit(imput_num)

sum(is.na(clean_data))
## [1] 0
clean_data
##      id idade estatura peso        imc renda  QI
## 3  1308    44     1.66   94  34.112353  2500 110
## 6  2628    35     1.64   79  29.372397  8500 107
## 7  2864    24     1.61   81  31.248794  6000 105
## 9  3504    35     1.79   58  18.101807  6000  98
## 10 3797    33     1.64   52 193.337299  3500 104
## 12 4334    39     1.64   85  31.603212  2000  95
## 14 4839    23     1.68   80  28.344671  9000 100
## 15 5041    26     1.79   64  19.974408  5500 108
## 18 8999    24     1.75   66   2.155102  4500  97
## 20 9694    21     1.62   80  30.483158  1500  99

Com esta regra, 50 % das obervações do banco de dados são descartadas.


A função drop.na permite excluir observações dos dados ausentes de uma um atributo de interesse.

A função filterpermite selecionar as observações com dados ausentes.

drop_imput_num <- imput_num %>%
  select (idade, estatura, peso, imc, renda, QI) %>%
  drop_na(QI) %>%
  mutate (QI = replace_na(renda, "unknow")) %>%
  filter(!complete.cases(.))

  drop_imput_num
##   idade estatura peso      imc renda     QI
## 1    49     1.77   57 18.19401    NA unknow
## 2    46       NA   69 24.15882  4500   4500
## 3    25     1.69   NA 25.55933  5500   5500
## 4    21   161.00   NA 29.70564    NA unknow
## 5    29       NA   58 21.30395 35000  35000
## 6    48     1.65   NA 27.91552  5500   5500
## 7    28     1.74   56 18.49650    NA unknow

LDD7 - Usar a média de todos os objetos da mesma classe para imputar o valor ausente

# MEAN

mean_imput_num <- imput_num

for (i in which(sapply(mean_imput_num, is.numeric))) 
  { 
  mean_imput_num[is.na(mean_imput_num[, i]), i] <- mean(mean_imput_num[, i],  na.rm = TRUE) 
}

sum(is.na(mean_imput_num))
## [1] 0
mean_imput_num
##      id idade  estatura     peso        imc     renda       QI
## 1  1010    18   1.71000 58.00000  19.835163  5500.000 101.5294
## 2  1271    34   1.79000 65.00000  20.286508   750.000 101.5294
## 3  1308    44   1.66000 94.00000  34.112353  2500.000 110.0000
## 4  1905    49   1.77000 57.00000  18.194006  6308.824 103.0000
## 5  1916    19   1.75000 82.00000  26.775510  1500.000 101.5294
## 6  2628    35   1.64000 79.00000  29.372397  8500.000 107.0000
## 7  2864    24   1.61000 81.00000  31.248794  6000.000 105.0000
## 8  2886    46  10.55111 69.00000  24.158818  4500.000  91.0000
## 9  3504    35   1.79000 58.00000  18.101807  6000.000  98.0000
## 10 3797    33   1.64000 52.00000 193.337299  3500.000 104.0000
## 11 4047    25   1.69000 69.64706  25.559329  5500.000 106.0000
## 12 4334    39   1.64000 85.00000  31.603212  2000.000  95.0000
## 13 4557    21 161.00000 69.64706  29.705644  6308.824 107.0000
## 14 4839    23   1.68000 80.00000  28.344671  9000.000 100.0000
## 15 5041    26   1.79000 64.00000  19.974408  5500.000 108.0000
## 16 6402    29  10.55111 58.00000  21.303949 35000.000  92.0000
## 17 7776    48   1.65000 69.64706  27.915519  5500.000 110.0000
## 18 8999    24   1.75000 66.00000   2.155102  4500.000  97.0000
## 19 9200    28   1.74000 56.00000  18.496499  6308.824  94.0000
## 20 9694    21   1.62000 80.00000  30.483158  1500.000  99.0000

Para exibir o resumo dos dados com a função summary, ignorando os dados ausentes antes da imputação de dados, pode-se usar a função na.rm = TRUE.

summary(imput_num, na.rm = TRUE)
##       id                idade          estatura            peso      
##  Length:20          Min.   :18.00   Min.   :  1.610   Min.   :52.00  
##  Class :character   1st Qu.:23.75   1st Qu.:  1.643   1st Qu.:58.00  
##  Mode  :character   Median :28.50   Median :  1.700   Median :66.00  
##                     Mean   :31.05   Mean   : 10.551   Mean   :69.65  
##                     3rd Qu.:36.00   3rd Qu.:  1.765   3rd Qu.:80.00  
##                     Max.   :49.00   Max.   :161.000   Max.   :94.00  
##                                     NA's   :2         NA's   :3      
##       imc              renda             QI       
##  Min.   :  2.155   Min.   :  750   Min.   : 91.0  
##  1st Qu.: 19.940   1st Qu.: 2500   1st Qu.: 97.0  
##  Median : 26.167   Median : 5500   Median :103.0  
##  Mean   : 32.548   Mean   : 6309   Mean   :101.5  
##  3rd Qu.: 29.900   3rd Qu.: 6000   3rd Qu.:107.0  
##  Max.   :193.337   Max.   :35000   Max.   :110.0  
##                    NA's   :3       NA's   :3
knitr::kable(mean_imput_num, 
             align = "c", 
             caption = "Imputação com a média nos dados ausentes ")
Imputação com a média nos dados ausentes
id idade estatura peso imc renda QI
1010 18 1.71000 58.00000 19.835163 5500.000 101.5294
1271 34 1.79000 65.00000 20.286508 750.000 101.5294
1308 44 1.66000 94.00000 34.112353 2500.000 110.0000
1905 49 1.77000 57.00000 18.194006 6308.824 103.0000
1916 19 1.75000 82.00000 26.775510 1500.000 101.5294
2628 35 1.64000 79.00000 29.372397 8500.000 107.0000
2864 24 1.61000 81.00000 31.248794 6000.000 105.0000
2886 46 10.55111 69.00000 24.158818 4500.000 91.0000
3504 35 1.79000 58.00000 18.101807 6000.000 98.0000
3797 33 1.64000 52.00000 193.337299 3500.000 104.0000
4047 25 1.69000 69.64706 25.559329 5500.000 106.0000
4334 39 1.64000 85.00000 31.603212 2000.000 95.0000
4557 21 161.00000 69.64706 29.705644 6308.824 107.0000
4839 23 1.68000 80.00000 28.344671 9000.000 100.0000
5041 26 1.79000 64.00000 19.974408 5500.000 108.0000
6402 29 10.55111 58.00000 21.303949 35000.000 92.0000
7776 48 1.65000 69.64706 27.915519 5500.000 110.0000
8999 24 1.75000 66.00000 2.155102 4500.000 97.0000
9200 28 1.74000 56.00000 18.496499 6308.824 94.0000
9694 21 1.62000 80.00000 30.483158 1500.000 99.0000

LDD7 - Usar a mediana de todos os objetos da mesma classe para imputar o valor ausente

# MEDIAN

median_imput_num <- imput_num

for (i in which(sapply(median_imput_num, is.numeric))) { 
  median_imput_num[is.na(median_imput_num[, i]),i] <-  median(median_imput_num[, i],  na.rm = TRUE)
}
sum(is.na(median_imput_num))
## [1] 0
median_imput_num
##      id idade estatura peso        imc renda  QI
## 1  1010    18     1.71   58  19.835163  5500 103
## 2  1271    34     1.79   65  20.286508   750 103
## 3  1308    44     1.66   94  34.112353  2500 110
## 4  1905    49     1.77   57  18.194006  5500 103
## 5  1916    19     1.75   82  26.775510  1500 103
## 6  2628    35     1.64   79  29.372397  8500 107
## 7  2864    24     1.61   81  31.248794  6000 105
## 8  2886    46     1.70   69  24.158818  4500  91
## 9  3504    35     1.79   58  18.101807  6000  98
## 10 3797    33     1.64   52 193.337299  3500 104
## 11 4047    25     1.69   66  25.559329  5500 106
## 12 4334    39     1.64   85  31.603212  2000  95
## 13 4557    21   161.00   66  29.705644  5500 107
## 14 4839    23     1.68   80  28.344671  9000 100
## 15 5041    26     1.79   64  19.974408  5500 108
## 16 6402    29     1.70   58  21.303949 35000  92
## 17 7776    48     1.65   66  27.915519  5500 110
## 18 8999    24     1.75   66   2.155102  4500  97
## 19 9200    28     1.74   56  18.496499  5500  94
## 20 9694    21     1.62   80  30.483158  1500  99
knitr::kable(median_imput_num, 
             align = "c", 
             caption = "Imputação com a mediana nos dados ausentes ")
Imputação com a mediana nos dados ausentes
id idade estatura peso imc renda QI
1010 18 1.71 58 19.835163 5500 103
1271 34 1.79 65 20.286508 750 103
1308 44 1.66 94 34.112353 2500 110
1905 49 1.77 57 18.194006 5500 103
1916 19 1.75 82 26.775510 1500 103
2628 35 1.64 79 29.372397 8500 107
2864 24 1.61 81 31.248794 6000 105
2886 46 1.70 69 24.158818 4500 91
3504 35 1.79 58 18.101807 6000 98
3797 33 1.64 52 193.337299 3500 104
4047 25 1.69 66 25.559329 5500 106
4334 39 1.64 85 31.603212 2000 95
4557 21 161.00 66 29.705644 5500 107
4839 23 1.68 80 28.344671 9000 100
5041 26 1.79 64 19.974408 5500 108
6402 29 1.70 58 21.303949 35000 92
7776 48 1.65 66 27.915519 5500 110
8999 24 1.75 66 2.155102 4500 97
9200 28 1.74 56 18.496499 5500 94
9694 21 1.62 80 30.483158 1500 99

Simputation Package.

 

Este pacote disponibiliza um conjunto de métodos para imputação simplificada de dados ausentes.

A estrutura para uso deste pacote usa a sintaxe impute_<model>(data, formula, [model-sprecific options]).

A saída é similar ao argumento data, exceto que os valores ausentes são imputados (quando possível), usando o modelo especificado.

A estrutura da formula de um objeto usa a sintaxe imputed ~model_especification [| grouping].

O segmento []é opcional.


LDD8 - Imputar dados usando regressão linear

imput_num_rl <- impute_lm(imput_num, estatura ~ peso + imc)

imput_num_rl
##      id idade   estatura peso        imc renda  QI
## 1  1010    18   1.710000   58  19.835163  5500  NA
## 2  1271    34   1.790000   65  20.286508   750  NA
## 3  1308    44   1.660000   94  34.112353  2500 110
## 4  1905    49   1.770000   57  18.194006    NA 103
## 5  1916    19   1.750000   82  26.775510  1500  NA
## 6  2628    35   1.640000   79  29.372397  8500 107
## 7  2864    24   1.610000   81  31.248794  6000 105
## 8  2886    46   1.719512   69  24.158818  4500  91
## 9  3504    35   1.790000   58  18.101807  6000  98
## 10 3797    33   1.640000   52 193.337299  3500 104
## 11 4047    25   1.690000   NA  25.559329  5500 106
## 12 4334    39   1.640000   85  31.603212  2000  95
## 13 4557    21 161.000000   NA  29.705644    NA 107
## 14 4839    23   1.680000   80  28.344671  9000 100
## 15 5041    26   1.790000   64  19.974408  5500 108
## 16 6402    29   1.760400   58  21.303949 35000  92
## 17 7776    48   1.650000   NA  27.915519  5500 110
## 18 8999    24   1.750000   66   2.155102  4500  97
## 19 9200    28   1.740000   56  18.496499    NA  94
## 20 9694    21   1.620000   80  30.483158  1500  99

 

imput_num_regression <- imput_num %>%
  
  # Label para o atributo ausente 
  
add_label_missings(estatura) %>%
  
  # Imputation para Linear Regression
  
  mutate(estatura = as.double(estatura)) %>%
  impute_lm(estatura ~ peso + imc)%>%
  
  # Visualização gráfica 
  
  ggplot(aes(imc, estatura, color = any_missing)) +
  geom_point()

imput_num_regression


LDD8 - Imputar dados usando Random Forest

imput_num_random_forest <- imput_num %>%
  
  # Label para o atributo ausente
  
add_label_missings(estatura) %>%
  
  # Imputation para  Decision trees (árvores de decisão)
  
  mutate(estatura = as.double(estatura)) %>%
  impute_rf(estatura ~ peso + imc) %>%

  # Visualização
  
  ggplot(aes(imc, estatura, color = any_missing))+
  geom_point()
## Warning: Package 'randomForest' is needed but not found. Returning original data
imput_num_random_forest
## Warning: Removed 2 rows containing missing values (geom_point).

Referências bibliográficas

 

Crawley, M.J. (2013). The R Book. Chichester, UK: Wiley.

Da Silva, L. A., Peres, S.M. & Boscarioli, C. (2016,2021). Introdução à mineração de dados: com aplicações em R. 1. ed. [Reimpr.]. Rio de Janeiro: LTC.

De Castro, L.N. & Ferrari, D.G. (2016). Introdução à mineração de dados: conceitos básicos, algoritmos, e aplicações. São Paulo: Editora Saraiva.

Goldschmidt, R. & Passos, E. (2006). Data mining: um guia prático. Conceitos, técnicas, ferramentas, orientações e aplicações. Rio de Janeiro: Campus/Elsevier.


 

Acesse a página Tabela de Cores HTML para acessar códigos de cores em HTML.

 

Acesse a página do RMarkdown.