Tipos e estruturas de dados
Introdução
Nem toda informação em um conjunto de dados é do mesmo tipo. Algumas variáveis representam números, outras textos, datas ou categorias. No R, cada tipo de dado é tratado de forma diferente, e reconhecer essas diferenças é essencial para evitar erros e realizar análises corretamente. O tipo de dado determina quais operações podemos realizar com cada variável. Por exemplo, podemos somar números, mas não faz sentido somar textos.
Tipos de dados
Na primeira aula realizamos operações matemáticas como esta:
Podemos usar a função class() para verificar a que classe de dados esses valores pertencem no R:
O resultado do código acima nos diz que estes números pertencem à classe numeric. Objetos dessa classe são armezanados internamente como números com casas decimais de alta precisão (double). Mesmo quando escrevemos um número inteiro como o 5, o R o armazena nesse formato.
Para especificar que queremos armazenar um número inteiro (integer), devemos utilizar a letra L após o número. Veja:
Na prática, em análises de dados, quase nunca é necessário usar, por exemplo, 5L em vez de 5. O R utiliza o tipo double como padrão para números e realiza conversões automáticas entre integer e double quando necessário. O uso explícito de integer é mais comum em outros contextos mais específicos.
Na aula passada, nós vimos que caminhos de diretórios são escritos entre aspas, da seguinte maneira:
"C:/Documentos/R/arquivo.xlsx"Que tipo de dado é esse? Execute o código abaixo:
Character representa textos, como por exemplo nome de amostras, localidades, tipos de rochas, códigos de identificação ou, como no caso acima, caminhos de arquivos. Não surpreendentemente, nós não podemos fazer operações matemáticas com esse tipo de dado:
Por mais que isso pareça óbvio, muitas vezes quando importamos dados, colunas com valores númericos podem ser lidas erroneamente como texto, o que pode acarretar em erros como o abaixo:
Nós podemos converter um objeto de classe character para numeric utilizando a função as.numeric():
Embora não possamos fazer operações matemáticas com textos, há uma série de outras operações que podemos fazer. Vamos ver algumas! Execute os comandos abaixo e tente entender o que cada função faz. Lembre-se de que você sempre pode consultar a documentação das funções.
Em muitos conjuntos de dados, precisamos trabalhar com datas, como por exemplo, data de coleta de uma amostra. Embora uma data pareça um texto, no R ela pode ser armazenada como um tipo específico, que permite realizar cálculos.
No entanto, assim como pode acontecer com valores númericos, muitas vezes datas são lidas como character pelo R. Podemos converter objetos de classe character para Date usando a função as.Date():
Além de data, o R tem um tipo específico para datas que incluem horas. Vamos usar as funções Sys.Date() e Sys.time() para ilustrar essa diferença. Essas funções nos dizem a data e a hora atual do nosso sistema, respectivamente:
Quando vemos POSIXt, significa que o objeto é uma data-hora. Uma data-hora pode ser armazenada como POSIXct, como vimos acima, ou como POSIXlt:
Em R, além de números, textos e datas, também trabalhamos com valores lógicos, que representam condições verdadeiras ou falsas. Esses valores são:
TRUE(verdadeiro)FALSE(falso)NA(dado ausente)
É importante digitá-los com todas as letras maiúsculas. Veja:
Obtemos valores lógicos ao comparar objetos com os operadores abaixo:
| Operador | Significado |
|---|---|
== |
igual a |
!= |
diferente de |
> |
maior que |
< |
menor que |
>= |
maior ou igual |
<= |
menor ou igual |
Vamos ver alguns exemplos:
Podemos combinar condições usando os seguinte operadores:
| Operador | Significado |
|---|---|
& |
e |
| |
ou |
O operador & só retorna TRUE se ambas as condições forem verdadeiras:
O operador | retorna TRUE se pelo menos uma condição for verdadeira:
Estrutura de dados
Agora, vamos trabalhar com um conjunto real de dados de terremotos disponibilizado pela United States Geological Survey (USGS). O arquivo contém informações como data e hora do evento, magnitude, profundidade, localização e outros atributos.
Embora dados recentes de terremotos possam ser baixados diretamente no site da USGS, para garantir que todos estejam trabalhando com o mesmo conjunto, utilize a versão disponibilizada nesta página, previamente obtida com registros dos meses de Janeiro e Fevereiro.
Vamos importar os dados como aprendemos na aula passada:
Perceba que utilizamos a função head() para visualizar apenas as primeiras linhas do nosso dataset. Isso é especialmente útil quando trabalhamos com tabelas longas e queremos ter uma ideia geral do seu conteúdo. Ao consultar a documentação da função, podemos observar que o número padrão de linhas exibidas é 6, mas que é possível definir outro valor, se desejarmos:
Se quisermos ver as últimas linhas, podemos usar a função tail() de maneira similar:
Nós importamos o dataset de terremotos e usamos a variável terremotos para referenciá-lo. Mas que tipo de objeto é terremotos?
Um data frame é uma das estruturas mais importantes do R para análise de dados. Ela representa uma lista de vetores de mesmo comprimento, organizada em formato tabular.
Para entender melhor, nós vamos montar o nosso próprio data frame do zero, começando pelos vetores. Nós criamos vetores com a função c():
Um vetor requer que todos os seus elementos sejam do mesmo tipo:
Então, o que ocorre se tentarmos criar um vetor misturando diferente tipos de dados?
O R realiza coerção automática de tipos seguindo uma hierarquia. O tipo character tem prioridade sobre numeric (double), que tem prioridade sobre integer, que por sua vez tem prioridade sobre logical.
Para misturar diferentes tipos de dados, podemos criar uma lista usando a função list():
Mas qual a vantagem de um vetor em relação à uma lista? Uma das principais vantagens de um vetor é que as operações funcionam elemento por elemento automaticamente.
Por exemplo, suponha que você queira converter a concentração de Al2O3 wt% para Al wt%. Você pode fazê-lo usando o fator de conversão 0.5293. Vejamos o que acontece se você aplica o fator de conversão à uma lista:
E o que acontece quando usamos o fator com um vetor?
Agora que entendemos o que é um vetor, podemos criar nosso data frame. Nós tínhamos definido os seguintes vetores previamente:
Nós podemos criar um data frame a partir desses vetores usando a função data.frame():
Se quisermos, também podemos nomear as colunas:
Agora que temos um entendimento maior do que são data frames, podemos revisitar o objeto terremotos. Vamos inspecioná-lo com a função str():
Duas variáveis foram lidas de maneira errada:
As colunas time e updated deveriam armazenar elementos do tipo data-hora (POSIXt). No entanto, os elementos são do tipo character.
Uma das maneiras de fazer a conversão de character para POSIXt seria através das funções as.POSIXct() ou as.POSIXlt(). Veja um exemplo:
Note que para usar essa função, nós precisamos especificar o formato da data-hora e o fuso horário, o que não é muito prático.
Para facilitar a nossa vida, o pacote lubridate foi desenvolvido. Para converter uma data-hora que contém anos, meses, dias, horas, minutos e segundos, podemos usar a função ymd_hms() desse pacote:
Observação:
Perceba que se rodarmos o código abaixo:
Nenhuma alteração ocorre na coluna:
Para isso, temos que atualizar as colunas usando o operador <-:
Agora, se inspecionarmos o objeto, os dados estarão corretamente armazenados:
Exercício
- Nesta aula nós trabalhamos com a função
read.csv(), que faz parte do R base. Para esse exercício, instale o pacotereadre use sua funçãoread_csv()no lugar deread.csv()para importar os dados de terremoto:
- Inspecione com a função
str()o objeto que você criou. Que diferença você nota em comparação com a estrutura que vimos anteriormente após usarread.csv()?
- Qual a classe do objeto
terremotos? Qual a classe do objetomineraisque criamos comread_excel()na aula passada?
- Tanto a função
read_csv()do pacotereadrquanto a funçãoread_excel()do pacotereadxlque vimos na aula passada fazem parte de uma coleção de pacotes chamada tidyverse. Que estrutura de dados os pacotes da coleção tidyverse usam? Por quê?
Considerações finais
Nesta aula, exploramos os principais tipos de dados do R e entendemos como cada um influencia as operações que podemos realizar. Também vimos como esses tipos se organizam em estruturas como vetores, listas e tabelas. Observamos que, ao importar dados reais, é fundamental verificar a estrutura e as classes das variáveis para evitar erros nas análises. Na próxima aula, vamos aprofundar a manipulação desses dados utilizando a coleção de pacotes tidyverse para filtrar, selecionar e transformar nossas tabelas de forma mais eficiente.