3.3 Filtrando e ordenando matrizes e data.frames

3.3.1 Filtragem de dados

Já vimos como fazer perguntas sobre vetores (Seção 2.6.1) e obter vetores lógicos ou valores de índices que nos permitem extrair ou filtrar de vetores os dados que satisfazem às condições das perguntas feitas. Aqui vamos estender isso para objetos de classe matrix e data.frame, porque é através de vetores lógicos ou de matrizes lógicas que podemos filtrar dados de objetos bidimensionais.

?iris # veja o help do R sobre Edgar Anderson's Iris Data que explica esses dados que vem com o R
class(iris)
## [1] "data.frame"
str(iris) # estrutura, veja as colunas
## 'data.frame':    150 obs. of  5 variables:
##  $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
##  $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
##  $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
##  $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
##  $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
# vamos filtrar os dados de uma das especies
unique(iris$Species) # vemos os valores únicos
## [1] setosa     versicolor virginica 
## Levels: setosa versicolor virginica
# ou, tendo em vista que é um fator
levels(iris$Species)
## [1] "setosa"     "versicolor" "virginica"
sp1 <- levels(iris$Species)[1]
# quais linhas correspondem a essa especie
vl <- iris$Species == sp1
sum(vl) # numero de linhas que satisfazem a pergunta
## [1] 50
nrow(iris) # numero total de linhas no data.frame
## [1] 150
# filtrando os dados eu simplesmente uso o vetor lógico como índice de linha. O novo objeto criado terá apenas as linhas em que vl é verdadeiro
iris.sp1 <- iris[vl, ]
nrow(iris.sp1) == sum(vl) # entao esta condição é verdadeira
## [1] TRUE
# filtrar segundo duas colunas
vl <- iris$Species == sp1 # seja da especie em sp1
sum(vl) # quantas sao?
## [1] 50
vl2 <- iris$Sepal.Length <= 5 # tenha sepala menor ou igual a 5
sum(vl2) # quantas sao?
## [1] 32
# combinando as duas perguntas
vll <- vl & vl2
sum(vll) # quantas sao?
## [1] 28
# filtrando
ff <- iris[vll, ]
class(ff) # novo data.frame resultando do filtro realizado
## [1] "data.frame"
nrow(ff) == sum(vll) # isso deve ser verdadeiro
## [1] TRUE

3.3.1.1 Dados com valores ausentes

As funçõesis.na() e na.omit() vistas anteriormente (Seção 2.6.3) permitem eliminar linhas e colunas que tenham valores ausentes. A presença de valores às vezes impede certas análises de serem executadas.

# vamos fazer uma cópia do objeto iris e modificar ele acrescentando alguns NAs
dd <- iris
# tem algum NA originalmente?
sum(is.na(dd)) # não tem
## [1] 0
# qual a dimensão?
dim(dd)
## [1] 150   5
# pega 10 valores aletórios entre 1:150 (linhas)
v1 <- sample(1:nrow(dd), size = 10, replace = F)
# nessas linhas acrescenta NAs na coluna 2
dd[v1, 2] <- NA
# pega outros 10 valores aletórios entre 1:150 (linhas)
v1 <- sample(1:nrow(dd), size = 10, replace = F)
# nessas linhas acrescenta NAs na coluna 3
dd[v1, 3] <- NA

# pronto agora temos um data.frame com NAs
sum(is.na(dd)) # tem 20 NAs na tabela
## [1] 20
# quais linhas tem NA
vl <- is.na(dd[, 2]) | is.na(dd[, 3]) # ou é NA em 2 ou em 3 que foi onde mudei
dd[vl, ]
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
12 4.8 3.4 NA 0.2 setosa
17 5.4 3.9 NA 0.4 setosa
20 5.1 NA 1.5 0.3 setosa
23 4.6 3.6 NA 0.2 setosa
29 5.2 NA 1.4 0.2 setosa
38 4.9 3.6 NA 0.1 setosa
41 5.0 NA 1.3 0.3 setosa
48 4.6 NA 1.4 0.2 setosa
71 5.9 3.2 NA 1.8 versicolor
74 6.1 2.8 NA 1.2 versicolor
81 5.5 NA 3.8 1.1 versicolor
85 5.4 NA 4.5 1.5 versicolor
92 6.1 3.0 NA 1.4 versicolor
108 7.3 NA 6.3 1.8 virginica
120 6.0 2.2 NA 1.5 virginica
139 6.0 3.0 NA 1.8 virginica
141 6.7 NA 5.6 2.4 virginica
144 6.8 3.2 NA 2.3 virginica
146 6.7 NA 5.2 2.3 virginica
150 5.9 NA 5.1 1.8 virginica
# use na.omit() para eliminar todas as linhas que NA em alguma coluna
sum(is.na(dd)) # tem 20 valores
## [1] 20
dd2 <- na.omit(dd)
sum(is.na(dd2)) # nao tem mais nenhum
## [1] 0

3.3.2 Ordenação de dados

Para ordenar matrizes e data.frames, é preciso entender a diferença entre duas funções:

  • sort() ordena um vetor e retorna os valores ordenados;

  • order() ordena um vetor e retorna os índices dos valores ordenados. É isso que deve ser utilizado para ordenar matrizes e data.frames.

?sort
?order
# ordenação
str(iris)
## 'data.frame':    150 obs. of  5 variables:
##  $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
##  $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
##  $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
##  $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
##  $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
# funcao SORT()
o1 <- sort(iris$Sepal.Length) # pega os valores ordenados da coluna comprimento de sépala
o1 # sao valores de sepalas do menor para o maior
##   [1] 4.3 4.4 4.4 4.4 4.5 4.6 4.6 4.6 4.6 4.7 4.7 4.8 4.8 4.8 4.8 4.8 4.9 4.9
##  [19] 4.9 4.9 4.9 4.9 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.1 5.1 5.1 5.1
##  [37] 5.1 5.1 5.1 5.1 5.1 5.2 5.2 5.2 5.2 5.3 5.4 5.4 5.4 5.4 5.4 5.4 5.5 5.5
##  [55] 5.5 5.5 5.5 5.5 5.5 5.6 5.6 5.6 5.6 5.6 5.6 5.7 5.7 5.7 5.7 5.7 5.7 5.7
##  [73] 5.7 5.8 5.8 5.8 5.8 5.8 5.8 5.8 5.9 5.9 5.9 6.0 6.0 6.0 6.0 6.0 6.0 6.1
##  [91] 6.1 6.1 6.1 6.1 6.1 6.2 6.2 6.2 6.2 6.3 6.3 6.3 6.3 6.3 6.3 6.3 6.3 6.3
## [109] 6.4 6.4 6.4 6.4 6.4 6.4 6.4 6.5 6.5 6.5 6.5 6.5 6.6 6.6 6.7 6.7 6.7 6.7
## [127] 6.7 6.7 6.7 6.7 6.8 6.8 6.8 6.9 6.9 6.9 6.9 7.0 7.1 7.2 7.2 7.2 7.3 7.4
## [145] 7.6 7.7 7.7 7.7 7.7 7.9
# em ordem decrescente
o2 <- sort(iris$Sepal.Length, decreasing = T)
o2 # sao valores de sepalas do maior para o menor
##   [1] 7.9 7.7 7.7 7.7 7.7 7.6 7.4 7.3 7.2 7.2 7.2 7.1 7.0 6.9 6.9 6.9 6.9 6.8
##  [19] 6.8 6.8 6.7 6.7 6.7 6.7 6.7 6.7 6.7 6.7 6.6 6.6 6.5 6.5 6.5 6.5 6.5 6.4
##  [37] 6.4 6.4 6.4 6.4 6.4 6.4 6.3 6.3 6.3 6.3 6.3 6.3 6.3 6.3 6.3 6.2 6.2 6.2
##  [55] 6.2 6.1 6.1 6.1 6.1 6.1 6.1 6.0 6.0 6.0 6.0 6.0 6.0 5.9 5.9 5.9 5.8 5.8
##  [73] 5.8 5.8 5.8 5.8 5.8 5.7 5.7 5.7 5.7 5.7 5.7 5.7 5.7 5.6 5.6 5.6 5.6 5.6
##  [91] 5.6 5.5 5.5 5.5 5.5 5.5 5.5 5.5 5.4 5.4 5.4 5.4 5.4 5.4 5.3 5.2 5.2 5.2
## [109] 5.2 5.1 5.1 5.1 5.1 5.1 5.1 5.1 5.1 5.1 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0
## [127] 5.0 5.0 4.9 4.9 4.9 4.9 4.9 4.9 4.8 4.8 4.8 4.8 4.8 4.7 4.7 4.6 4.6 4.6
## [145] 4.6 4.5 4.4 4.4 4.4 4.3
# FUNCAO order()
# qual o indice dos valores ordenados em ordem crescente?
o3 <- order(iris$Sepal.Length)
o3 # esses valores correspondem aos INDICES dos valores ordenados
##   [1]  14   9  39  43  42   4   7  23  48   3  30  12  13  25  31  46   2  10
##  [19]  35  38  58 107   5   8  26  27  36  41  44  50  61  94   1  18  20  22
##  [37]  24  40  45  47  99  28  29  33  60  49   6  11  17  21  32  85  34  37
##  [55]  54  81  82  90  91  65  67  70  89  95 122  16  19  56  80  96  97 100
##  [73] 114  15  68  83  93 102 115 143  62  71 150  63  79  84  86 120 139  64
##  [91]  72  74  92 128 135  69  98 127 149  57  73  88 101 104 124 134 137 147
## [109]  52  75 112 116 129 133 138  55 105 111 117 148  59  76  66  78  87 109
## [127] 125 141 145 146  77 113 144  53 121 140 142  51 103 110 126 130 108 131
## [145] 106 118 119 123 136 132
# entao para ver os valores ordenados
iris$Sepal.Length[o3]
##   [1] 4.3 4.4 4.4 4.4 4.5 4.6 4.6 4.6 4.6 4.7 4.7 4.8 4.8 4.8 4.8 4.8 4.9 4.9
##  [19] 4.9 4.9 4.9 4.9 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.1 5.1 5.1 5.1
##  [37] 5.1 5.1 5.1 5.1 5.1 5.2 5.2 5.2 5.2 5.3 5.4 5.4 5.4 5.4 5.4 5.4 5.5 5.5
##  [55] 5.5 5.5 5.5 5.5 5.5 5.6 5.6 5.6 5.6 5.6 5.6 5.7 5.7 5.7 5.7 5.7 5.7 5.7
##  [73] 5.7 5.8 5.8 5.8 5.8 5.8 5.8 5.8 5.9 5.9 5.9 6.0 6.0 6.0 6.0 6.0 6.0 6.1
##  [91] 6.1 6.1 6.1 6.1 6.1 6.2 6.2 6.2 6.2 6.3 6.3 6.3 6.3 6.3 6.3 6.3 6.3 6.3
## [109] 6.4 6.4 6.4 6.4 6.4 6.4 6.4 6.5 6.5 6.5 6.5 6.5 6.6 6.6 6.7 6.7 6.7 6.7
## [127] 6.7 6.7 6.7 6.7 6.8 6.8 6.8 6.9 6.9 6.9 6.9 7.0 7.1 7.2 7.2 7.2 7.3 7.4
## [145] 7.6 7.7 7.7 7.7 7.7 7.9
# então isso deve ser totalmente verdadeiro:
iris$Sepal.Length[o3] == sort(iris$Sepal.Length) # as comparações para a par são identicas
##   [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
##  [16] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
##  [31] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
##  [46] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
##  [61] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
##  [76] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
##  [91] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [106] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [121] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [136] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
# então esta expressão também é verdadeira:
sum(iris$Sepal.Length[o3] == sort(iris$Sepal.Length)) == nrow(iris)
## [1] TRUE
# portanto a função sort ordena os valores e funcao order mostra apenas os indices dos valores ordenados. Assim, posso usar a funcao order() para ordenar data.frames, matrizes e vetores
idx <- order(iris$Sepal.Length) # indice das linhas ordenadas segundo o comprimento das sepalas
# compara com o original:
sum(iris$Sepal.Length[idx] == iris$Sepal.Length) == nrow(iris) # é FALSO porque em iris as linhas não estão originalmente ordenadas segundo o comprimento.
## [1] FALSE
# vamos mudar isso
novo.iris <- iris[idx, ] # pego o vetor de indices dos valores ordenados e uso na indexacao para ordenar o objeto original segunda a coluna escolhida
idx2 <- order(novo.iris$Sepal.Length) # indice das linhas ordenadas segundo o comprimento das sepalas
# note que agora essa expressão é verdadeira, porque o original já está ordenado segundo essa coluna
sum(novo.iris$Sepal.Length[idx2] == novo.iris$Sepal.Length) == nrow(novo.iris) # é VERDADEIRO
## [1] TRUE
# AGORA ORDENANDO POR MULTIPLAS COLUNAS
idx <- order(iris$Species, iris$Sepal.Length, decreasing = TRUE) # por especie e por sepala em ordem decrescente

# ordena segundo essas duas colunas
novo.iris <- iris[idx, ]
novo.iris[, c("Species", "Sepal.Length")]
Species Sepal.Length
132 virginica 7.9
118 virginica 7.7
119 virginica 7.7
123 virginica 7.7
136 virginica 7.7
106 virginica 7.6
131 virginica 7.4
108 virginica 7.3
110 virginica 7.2
126 virginica 7.2
130 virginica 7.2
103 virginica 7.1
121 virginica 6.9
140 virginica 6.9
142 virginica 6.9
113 virginica 6.8
144 virginica 6.8
109 virginica 6.7
125 virginica 6.7
141 virginica 6.7
145 virginica 6.7
146 virginica 6.7
105 virginica 6.5
111 virginica 6.5
117 virginica 6.5
148 virginica 6.5
112 virginica 6.4
116 virginica 6.4
129 virginica 6.4
133 virginica 6.4
138 virginica 6.4
101 virginica 6.3
104 virginica 6.3
124 virginica 6.3
134 virginica 6.3
137 virginica 6.3
147 virginica 6.3
127 virginica 6.2
149 virginica 6.2
128 virginica 6.1
135 virginica 6.1
120 virginica 6.0
139 virginica 6.0
150 virginica 5.9
102 virginica 5.8
115 virginica 5.8
143 virginica 5.8
114 virginica 5.7
122 virginica 5.6
107 virginica 4.9
51 versicolor 7.0
53 versicolor 6.9
77 versicolor 6.8
66 versicolor 6.7
78 versicolor 6.7
87 versicolor 6.7
59 versicolor 6.6
76 versicolor 6.6
55 versicolor 6.5
52 versicolor 6.4
75 versicolor 6.4
57 versicolor 6.3
73 versicolor 6.3
88 versicolor 6.3
69 versicolor 6.2
98 versicolor 6.2
64 versicolor 6.1
72 versicolor 6.1
74 versicolor 6.1
92 versicolor 6.1
63 versicolor 6.0
79 versicolor 6.0
84 versicolor 6.0
86 versicolor 6.0
62 versicolor 5.9
71 versicolor 5.9
68 versicolor 5.8
83 versicolor 5.8
93 versicolor 5.8
56 versicolor 5.7
80 versicolor 5.7
96 versicolor 5.7
97 versicolor 5.7
100 versicolor 5.7
65 versicolor 5.6
67 versicolor 5.6
70 versicolor 5.6
89 versicolor 5.6
95 versicolor 5.6
54 versicolor 5.5
81 versicolor 5.5
82 versicolor 5.5
90 versicolor 5.5
91 versicolor 5.5
85 versicolor 5.4
60 versicolor 5.2
99 versicolor 5.1
61 versicolor 5.0
94 versicolor 5.0
58 versicolor 4.9
15 setosa 5.8
16 setosa 5.7
19 setosa 5.7
34 setosa 5.5
37 setosa 5.5
6 setosa 5.4
11 setosa 5.4
17 setosa 5.4
21 setosa 5.4
32 setosa 5.4
49 setosa 5.3
28 setosa 5.2
29 setosa 5.2
33 setosa 5.2
1 setosa 5.1
18 setosa 5.1
20 setosa 5.1
22 setosa 5.1
24 setosa 5.1
40 setosa 5.1
45 setosa 5.1
47 setosa 5.1
5 setosa 5.0
8 setosa 5.0
26 setosa 5.0
27 setosa 5.0
36 setosa 5.0
41 setosa 5.0
44 setosa 5.0
50 setosa 5.0
2 setosa 4.9
10 setosa 4.9
35 setosa 4.9
38 setosa 4.9
12 setosa 4.8
13 setosa 4.8
25 setosa 4.8
31 setosa 4.8
46 setosa 4.8
3 setosa 4.7
30 setosa 4.7
4 setosa 4.6
7 setosa 4.6
23 setosa 4.6
48 setosa 4.6
42 setosa 4.5
9 setosa 4.4
39 setosa 4.4
43 setosa 4.4
14 setosa 4.3
# para cada especie esta ordenado por sepala:
novo.iris[novo.iris$Species == "versicolor", ]$Sepal.Length
##  [1] 7.0 6.9 6.8 6.7 6.7 6.7 6.6 6.6 6.5 6.4 6.4 6.3 6.3 6.3 6.2 6.2 6.1 6.1 6.1
## [20] 6.1 6.0 6.0 6.0 6.0 5.9 5.9 5.8 5.8 5.8 5.7 5.7 5.7 5.7 5.7 5.6 5.6 5.6 5.6
## [39] 5.6 5.5 5.5 5.5 5.5 5.5 5.4 5.2 5.1 5.0 5.0 4.9
novo.iris[novo.iris$Species == "virginica", ]$Sepal.Length
##  [1] 7.9 7.7 7.7 7.7 7.7 7.6 7.4 7.3 7.2 7.2 7.2 7.1 6.9 6.9 6.9 6.8 6.8 6.7 6.7
## [20] 6.7 6.7 6.7 6.5 6.5 6.5 6.5 6.4 6.4 6.4 6.4 6.4 6.3 6.3 6.3 6.3 6.3 6.3 6.2
## [39] 6.2 6.1 6.1 6.0 6.0 5.9 5.8 5.8 5.8 5.7 5.6 4.9