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.
# veja o help do R sobre Edgar Anderson's Iris Data que explica esses dados que vem com o R ?iris
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"
<- levels(iris$Species)[1]
sp1 # quais linhas correspondem a essa especie
<- iris$Species == sp1
vl 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[vl, ]
iris.sp1 nrow(iris.sp1) == sum(vl) # entao esta condição é verdadeira
## [1] TRUE
# filtrar segundo duas colunas
<- iris$Species == sp1 # seja da especie em sp1
vl sum(vl) # quantas sao?
## [1] 50
<- iris$Sepal.Length <= 5 # tenha sepala menor ou igual a 5
vl2 sum(vl2) # quantas sao?
## [1] 32
# combinando as duas perguntas
<- vl & vl2
vll sum(vll) # quantas sao?
## [1] 28
# filtrando
<- iris[vll, ]
ff 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
<- iris
dd # 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)
<- sample(1:nrow(dd), size = 10, replace = F)
v1 # nessas linhas acrescenta NAs na coluna 2
2] <- NA
dd[v1, # pega outros 10 valores aletórios entre 1:150 (linhas)
<- sample(1:nrow(dd), size = 10, replace = F)
v1 # nessas linhas acrescenta NAs na coluna 3
3] <- NA
dd[v1,
# pronto agora temos um data.frame com NAs
sum(is.na(dd)) # tem 20 NAs na tabela
## [1] 20
# quais linhas tem NA
<- is.na(dd[, 2]) | is.na(dd[, 3]) # ou é NA em 2 ou em 3 que foi onde mudei
vl 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
<- na.omit(dd)
dd2 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 edata.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()
<- sort(iris$Sepal.Length) # pega os valores ordenados da coluna comprimento de sépala
o1 # sao valores de sepalas do menor para o maior o1
## [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
<- sort(iris$Sepal.Length, decreasing = T)
o2 # sao valores de sepalas do maior para o menor o2
## [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?
<- order(iris$Sepal.Length)
o3 # esses valores correspondem aos INDICES dos valores ordenados o3
## [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
$Sepal.Length[o3] iris
## [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:
$Sepal.Length[o3] == sort(iris$Sepal.Length) # as comparações para a par são identicas iris
## [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
<- order(iris$Sepal.Length) # indice das linhas ordenadas segundo o comprimento das sepalas
idx # 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
<- iris[idx, ] # pego o vetor de indices dos valores ordenados e uso na indexacao para ordenar o objeto original segunda a coluna escolhida
novo.iris <- order(novo.iris$Sepal.Length) # indice das linhas ordenadas segundo o comprimento das sepalas idx2
# 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
<- order(iris$Species, iris$Sepal.Length, decreasing = TRUE) # por especie e por sepala em ordem decrescente
idx
# ordena segundo essas duas colunas
<- iris[idx, ]
novo.iris c("Species", "Sepal.Length")] novo.iris[,
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:
$Species == "versicolor", ]$Sepal.Length novo.iris[novo.iris
## [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
$Species == "virginica", ]$Sepal.Length novo.iris[novo.iris
## [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