7.7 Lidando com com dados faltantes

Dados faltantes (NAs) são inevitáveis e em qualquer processamento de dados reais nós precisamos determinar se existem dados faltantes e a quantidade de observações válidas. É importante também, saber o efeito que eles tem nos cálculos, as funcionalidades para identificá-los e substituí-los se necessários.

Vamos substituir alguns valores da prec_alt por NA para poder tratar de dados faltantes usando as diferentes funcionalidades que o oferece para isso.

prec_alt[c(3, 4, 11)] <- NA
prec_alt
#> jan fev mar abr mai jun jul ago set out nov dez 
#> 250 200  NA  NA   0  NA  21  42 100 120  NA 208

7.7.1 Identificação e remoção de NAs

Para identificar NAs em um vetor, a função específica para isso é a is.na().

is.na(prec_alt)
#>   jan   fev   mar   abr   mai   jun   jul   ago   set   out   nov   dez 
#> FALSE FALSE  TRUE  TRUE FALSE  TRUE FALSE FALSE FALSE FALSE  TRUE FALSE

Também podemos usá-la aninhada com a função which() para obter os índices dos elementos faltantes.

which(is.na(prec_alt))
#> mar abr jun nov 
#>   3   4   6  11

Novos usuários do R tentam identificar dados faltantes com a expressão:

prec_alt == NA
#> jan fev mar abr mai jun jul ago set out nov dez 
#>  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA

O que produzirá somente NAs mesmo que o vetor testado possua algum NA. Isso ocorre pela regra de qualquer operação com NAs resulta em NAs.

Para verificar se há algum dado faltante em um vetor usamos a função anyNA() e para quantificar o total de observações faltantes combinamos as expressões sum() e is.na():

anyNA(prec_alt)
#> [1] TRUE
sum(is.na(prec_alt))
#> [1] 4

A remoção dos elementos faltantes de um vetor é moleza. É só combinar o operador negação ! e is.na() por indexação lógica:

prec_alt[!is.na(prec_alt)]
#> jan fev mai jul ago set out dez 
#> 250 200   0  21  42 100 120 208
# outra forma equivalente
#prec_alt[-which(is.na(prec_alt))]

Uma alternativa mais sofisticada é a função na.omit(). Ela não só remove os valores faltantes, mas como também guarda a localização dos dados faltantes. Esta informação é armazenada na lista de atributos do vetor.

prec_alt_sem_falt <- na.omit(prec_alt)
attributes(prec_alt_sem_falt)
#> $names
#> [1] "jan" "fev" "mai" "jul" "ago" "set" "out" "dez"
#> 
#> $na.action
#> mar abr jun nov 
#>   3   4   6  11 
#> attr(,"class")
#> [1] "omit"

As posições originais dos dados faltantes descartados podem ser obtidas com:

attr(
  x = prec_alt_sem_falt,
  which = "na.action"
)
#> mar abr jun nov 
#>   3   4   6  11 
#> attr(,"class")
#> [1] "omit"

Quando trabalhamos com vetores grandes que contenham várias falhas é útil saber a posição da sequência de dados consecutivos válidos mais longa. A função na.contiguous() retornará somente elementos daquela sequência.

prec_alt_val_long <- na.contiguous(prec_alt)
prec_alt_val_long
#> jul ago set out 
#>  21  42 100 120 
#> attr(,"na.action")
#> [1]  1  2  3  4  5  6 11 12
#> attr(,"class")
#> [1] "omit"
#> attr(,"tsp")
#> [1]  7 10  1

7.7.2 Indexação com NAs

Suponha que queremos extrair um conjunto de elementos de prec_clim baseado em inds_na.

prec_alt > 220
#>   jan   fev   mar   abr   mai   jun   jul   ago   set   out   nov   dez 
#>  TRUE FALSE    NA    NA FALSE    NA FALSE FALSE FALSE FALSE    NA FALSE

O interesse é extrair os valores de prec_clim quando a prec_alt superou 220 mm. A expressão para essa seleção é:

prec_clim[prec_alt > 220]
#> [1] 230  NA  NA  NA  NA

o resultado da filtragem foi um vetor com o resultado da condição de prec_clim para qual prec_alt > 220 e também NAs. Isto é um resultado que provavelmente ninguém deseja.

Se nós queremos extrair os valores de prec_clim para os quais prec_alt não é faltante e também superior a 220 nós devemos usar a seguinte expressão:

prec_clim[!is.na(prec_alt) & prec_alt > 220]
#> [1] 230

A moral da história aqui é que na prática quando você tem NAs em índices (ou seja, nos valores de qualquer vetor dentro do colchetes) o pode retornar algo diferente do que era esperado.

Uma função para filtragem de dados que é capaz de dar conta disso mais prontamente é função subset() (que pode ser traduzida como subconjunto) que recebe os dados no primeiro argumento (x) e a expressão lógica no segundo (argumento subset de mesmo nome da função).

subset(
  x = prec_clim,
  subset = prec_alt > 220
)
#> [1] 230

7.7.3 Efeito de NAs em funções

Na seção 5.2.3 vimos que qualquer operação com NA resulta em NA. Algumas funções úteis merecem ser enfatizadas quando usadas em vetores com dados faltantes.

A função range() retorna a amplitude de variação dos valores em um vetor.

range(prec_alt)
#> [1] NA NA

Como prec_alt possui dados faltantes ela retornará NA. Assim como várias outras funções matemáticas básicas no a função range() permite especificar o argumento na.rm = TRUE para calcular o resultado após omitir os valores faltantes.

range(prec_alt, na.rm = TRUE)
#> [1]   0 250

Logo, prec_alt varia de um mínimo 0 a um máximo de 250.

Diversas funções tem essa funcionalidade, entre elas as mais usadas para estatísticas descritivas, como:

# prec máx. mensal
max(prec_alt, na.rm = TRUE)
#> [1] 250
# pŕec min mensal
min(prec_alt, na.rm = TRUE)
#> [1] 0
# prec total anual
sum(prec_alt, na.rm = TRUE)
#> [1] 941
# prec média
mean(prec_alt, na.rm = TRUE)
#> [1] 117.625
# mediana da prec 
median(prec_alt, na.rm = TRUE)
#> [1] 110
# desvio padrão
sd(prec_alt, na.rm = TRUE)
#> [1] 93.87216
# variância
var(prec_alt, na.rm = TRUE)
#> [1] 8811.982

A função summary() fornece um resumo estatístico de uma variável, incluindo: mínimo, 1° quartil, mediana, média, 3° quartil, máximo e o número de casos faltantes (se aplicável).

summary(prec_alt)
#>    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
#>    0.00   36.75  110.00  117.62  202.00  250.00       4