3.10 Mais sobre data frames
Chegou a hora de usarmos tudo o que aprendemos na seção anterior para exploramos ao máximo o nosso objeto favorito: o data frame.
Na seção anterior, nós dissemos que data frames são listas. Isso é importante pois todas as propriedades de uma lista valem para um data frame.
A melhor forma de entender essa equivalência é ver um data frame representado como uma lista.
as.list(mtcars)
## $mpg
## [1] 21.0 21.0 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 17.8 16.4 17.3 15.2 10.4
## [16] 10.4 14.7 32.4 30.4 33.9 21.5 15.5 15.2 13.3 19.2 27.3 26.0 30.4 15.8 19.7
## [31] 15.0 21.4
##
## $cyl
## [1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4
##
## $disp
## [1] 160.0 160.0 108.0 258.0 360.0 225.0 360.0 146.7 140.8 167.6 167.6 275.8
## [13] 275.8 275.8 472.0 460.0 440.0 78.7 75.7 71.1 120.1 318.0 304.0 350.0
## [25] 400.0 79.0 120.3 95.1 351.0 145.0 301.0 121.0
##
## $hp
## [1] 110 110 93 110 175 105 245 62 95 123 123 180 180 180 205 215 230 66 52
## [20] 65 97 150 150 245 175 66 91 113 264 175 335 109
##
## $drat
## [1] 3.90 3.90 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 3.92 3.07 3.07 3.07 2.93
## [16] 3.00 3.23 4.08 4.93 4.22 3.70 2.76 3.15 3.73 3.08 4.08 4.43 3.77 4.22 3.62
## [31] 3.54 4.11
##
## $wt
## [1] 2.620 2.875 2.320 3.215 3.440 3.460 3.570 3.190 3.150 3.440 3.440 4.070
## [13] 3.730 3.780 5.250 5.424 5.345 2.200 1.615 1.835 2.465 3.520 3.435 3.840
## [25] 3.845 1.935 2.140 1.513 3.170 2.770 3.570 2.780
##
## $qsec
## [1] 16.46 17.02 18.61 19.44 17.02 20.22 15.84 20.00 22.90 18.30 18.90 17.40
## [13] 17.60 18.00 17.98 17.82 17.42 19.47 18.52 19.90 20.01 16.87 17.30 15.41
## [25] 17.05 18.90 16.70 16.90 14.50 15.50 14.60 18.60
##
## $vs
## [1] 0 0 1 1 0 1 0 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 1 0 1 0 0 0 1
##
## $am
## [1] 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1
##
## $gear
## [1] 4 4 4 3 3 3 3 4 4 4 4 3 3 3 3 3 3 4 4 4 3 3 3 3 3 4 5 5 5 5 5 4
##
## $carb
## [1] 4 4 1 1 2 1 4 2 2 4 4 3 3 3 4 4 4 1 2 1 1 2 2 4 2 1 2 2 4 6 8 2
O código acima nos permite ver o data frame mtcars
representado como uma lista. Veja que cada coluna da base se transforma em um elemento da lista. E o nome de cada coluna vira o nome de cada posição. Isso é interessante, pois podemos usar nos data frames as mesmas operações que aprendemos para listas.
Por exemplo, podemos usar o operador $
para acessar cada elemento da lista, isto é, cada coluna do data frame.
$mpg
mtcars## [1] 21.0 21.0 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 17.8 16.4 17.3 15.2 10.4
## [16] 10.4 14.7 32.4 30.4 33.9 21.5 15.5 15.2 13.3 19.2 27.3 26.0 30.4 15.8 19.7
## [31] 15.0 21.4
E assim como cada elemento de uma lista também é uma lista, cada elemento (coluna) de um data frame também é um data frame.
1]
mtcars[## mpg
## Mazda RX4 21.0
## Mazda RX4 Wag 21.0
## Datsun 710 22.8
## Hornet 4 Drive 21.4
## Hornet Sportabout 18.7
## Valiant 18.1
## Duster 360 14.3
## Merc 240D 24.4
## Merc 230 22.8
## Merc 280 19.2
## Merc 280C 17.8
## Merc 450SE 16.4
## Merc 450SL 17.3
## Merc 450SLC 15.2
## Cadillac Fleetwood 10.4
## Lincoln Continental 10.4
## Chrysler Imperial 14.7
## Fiat 128 32.4
## Honda Civic 30.4
## Toyota Corolla 33.9
## Toyota Corona 21.5
## Dodge Challenger 15.5
## AMC Javelin 15.2
## Camaro Z28 13.3
## Pontiac Firebird 19.2
## Fiat X1-9 27.3
## Porsche 914-2 26.0
## Lotus Europa 30.4
## Ford Pantera L 15.8
## Ferrari Dino 19.7
## Maserati Bora 15.0
## Volvo 142E 21.4
class(mtcars[1])
## [1] "data.frame"
Mas se data frames são listas, por que existe a classe data frame? Na verdade, data frames são um tipo especial de listas, que têm as seguintes propriedades:
Todos os seus elementos (colunas) precisam ter o mesmo comprimento (número de linhas).
Todos os seus elementos (colunas) precisam ser nomeados.
Data frames têm 2 dimensões.
As propriedades (1) e (2) se devem ao formato das bases de dados. Elas são retangulares8 — observamos as mesmas variáveis (colunas) para todas as unidades amostrais (linhas)9 —, e precisam ter algum nome especificando as colunas.
Da mesma forma que podemos ver um data frame como uma lista, também podemos fazer o inverso.
<- list(
dados_cliente cliente = c("Ana Silva", "Beto Pereira", "Carla Souza"),
idade = c(25, 30, 23),
estado_civil = c(NA, "Solteiro", "Casada")
)
dados_cliente ## $cliente
## [1] "Ana Silva" "Beto Pereira" "Carla Souza"
##
## $idade
## [1] 25 30 23
##
## $estado_civil
## [1] NA "Solteiro" "Casada"
as.data.frame(dados_cliente)
## cliente idade estado_civil
## 1 Ana Silva 25 <NA>
## 2 Beto Pereira 30 Solteiro
## 3 Carla Souza 23 Casada
Quando tivermos valores faltantes na nossa base (células vazias no Excel), eles serão representados por NA
nos data frames.
Observe que não conseguimos transformar uma lista em data frame se os elementos da lista não tiverem o mesmo comprimento.
<- list(
dados_cliente cliente = c("Ana Silva", "Beto Pereira", "Carla Souza"),
idade = c(25, 30),
estado_civil = c(NA, "Solteiro", "Casada")
)
as.data.frame(dados_cliente)
## Error in (function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE, : arguments imply differing number of rows: 3, 2
Transformar uma lista não nomeada em data frame é possível, mas o R cria nomes nada agradáveis para as colunas.
<- list(
dados_cliente c("Ana Silva", "Beto Pereira", "Carla Souza"),
c(25, 30, 23),
c(NA, "Solteiro", "Casada")
)
as.data.frame(dados_cliente)
## c..Ana.Silva....Beto.Pereira....Carla.Souza.. c.25..30..23.
## 1 Ana Silva 25
## 2 Beto Pereira 30
## 3 Carla Souza 23
## c.NA...Solteiro....Casada..
## 1 <NA>
## 2 Solteiro
## 3 Casada
A propriedade (3) é atribuída aos data frames para que possamos aproveitar melhor dessa estrutura retangular dentro do R. Na prática, essas duas dimensões representam nada mais que as linhas e as colunas da base. Essa é a maior diferença entre uma lista e um data frame.
class(mtcars)
## [1] "data.frame"
dim(mtcars)
## [1] 32 11
O resultado do código dim(mtcars)
nos dá as seguintes informações:
O data frame mtcars tem duas dimensões (como todo data frame).
A primeira dimensão tem comprimento 32 e a segunda dimensão tem comprimento 11. Em outras palavras: a base
mtcars
tem 32 linhas e 11 colunas.
Veja a seguir que listas não têm dimensão.
<- as.list(mtcars)
mtcars_como_lista
class(mtcars_como_lista)
## [1] "list"
dim(mtcars_como_lista)
## NULL
Ter duas dimensões significa que devemos usar dois índices para acessar os valores de um data frame (fazer subsetting). Para isso, ainda usamos o colchete, mas agora com dois argumentos: [linha, coluna]
.
2, 3]
mtcars[## [1] 160
O código acima está nos devolvendo o valor presente na segunda linha da terceira coluna da base mtcars
.
Também podemos pegar todas as linhas de uma coluna ou todas as colunas de uma linha deixando um dos argumentos vazio:
# Todas as linhas da coluna 1
1]
mtcars[,## [1] 21.0 21.0 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 17.8 16.4 17.3 15.2 10.4
## [16] 10.4 14.7 32.4 30.4 33.9 21.5 15.5 15.2 13.3 19.2 27.3 26.0 30.4 15.8 19.7
## [31] 15.0 21.4
# Todas as colunas da linha 1
1,]
mtcars[## mpg cyl disp hp drat wt qsec vs am gear carb
## Mazda RX4 21 6 160 110 3.9 2.62 16.46 0 1 4 4
Por fim, lembrando que dentro de cada coluna temos um vetor, podemos usar os testes lógicos para filtrar as linhas do nosso data frame conforme alguma regra.
$cyl == 4
mtcars## [1] FALSE FALSE TRUE FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
## [13] FALSE FALSE FALSE FALSE FALSE TRUE TRUE TRUE TRUE FALSE FALSE FALSE
## [25] FALSE TRUE TRUE TRUE FALSE FALSE FALSE TRUE
$cyl == 4, ]
mtcars[mtcars## mpg cyl disp hp drat wt qsec vs am gear carb
## Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
## Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
## Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
## Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
## Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
## Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1
## Toyota Corona 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1
## Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
## Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
## Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2
## Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2
O código mtcars$cyl == 4
nos diz em quais linhas estão os carros com 4 cilindros. Quando usamos o vetor de TRUE
e FALSE
resultante dentro do subsetting das linhas em mtcars[mtcars$cyl == 4, ]
, o R nos devolve todos as colunas dos carros com 4 cilindros. A regra é simples: linha com TRUE
é retornada, linha com FALSE
não.
Encerramos aqui a nossa primeira conversa sobre data frames
para falar de outra estrutura muito importante dentro do R: as funções.
Exercícios
1. Quais códigos abaixo retornam um vetor com a coluna mpg
do data frame mtcars
?
a.
mtcars$mpg
b.
mtcars[ , 3]
c.
mtcars("mpg")
d.
mtcars[ , "mpg"]
e.
mtcars.mpg
f.
mtcars[ , 1]
g.
mtcars[1, 1]
h.
mpg$mtcars
2. Para que serve a função str()
. Dê um exemplo do seu uso.
3. Para que serve a função names()
. Dê um exemplo do seu uso.
4. Use o data frame airquality
para responder às questões abaixo:
a. Quantas colunas
airquality
tem?b. Quantas linhas
airquality
tem?c. O que a função
head()
retorna?d. Quais são os nomes das colunas?
e. Qual é a classe da coluna
Ozone
?
5. Desafio. Calculando desvio-padrão no R. Use o data frame airquality
para responder às questões abaixo:
a. Tire a média da coluna Ozone e guarde em um objeto.
b. Guarde em um objeto o vetor correspondente à coluna Ozone subtraída da sua própria média (calculada em no item a).
c. Eleve o vetor calculado em (b) ao quadrado. Salve o resultado em um novo objeto.
d. Tire a média do vetor calculado em (c) e salve o resultado em um objeto chamado
variancia
. Em seguida, calcule a raiz quadrada desse valor e salve em um objeto chamadodesvio_padrao
.e. Compare o valor de
desvio_padrao
comsd(airquality$Ozone, na.rm=TRUE)
e pesquise por que os valores não são iguais. Dica: veja a documentação da funçãosd()
.
6. Use o data frame airquality
para responder às questões abaixo.
a. Conte quantos
NAs
tem na colunaSolar.R
.b. Filtre a tabela
airquality
com apenas linhas em queSolar.R
éNA
.c. Filtre a tabela
airquality
com apenas linhas em queSolar.R
não éNA
.d. Filtre a tabela
airquality
com apenas linhas em queSolar.R
não éNA
eMonth
é igual a 5.