Escolar Documentos
Profissional Documentos
Cultura Documentos
11
12
Introdução
Este documento foi criado para ser uma referência inicial aos alunos do Curso de R da Fundação
João Pinheiro (FJP), como uma iniciativa do projeto de Transformação Digital da Diretoria de Es
tatística e Informações (DIREI). Em linhas gerais, este curso apresenta os conceitos fundamentais
da linguagem R e serve de guia para os primeiros passos na utilização do RStudio para a análise de
dados.
No primeiro capítulo, é feita uma breve recaptulação do R e sua história. No segundo, são apre
sentadas noções básicas de R, sobretudo seu uso por meio do RStudio, por exemplo: a utilização
do Console, como realizar operações matemáticas, como designar objetos, como executar coman
dos no R (introdução às funções), onde conseguir ajuda, as principais referências para a Ciência
de dados no R, como executar Scripts e o que são pacotes e como utilizálos. O terceiro capítulo,
por fim, concentrase no principal objeto do R: o vetor. São apresentados os conceitos básicos de
vetores, como criálos, utilizálos, seus tipos, suas propriedades, como selecionar seus elementos,
entre outros aspectos. O capítulo foca principalmente em vetores atômicos, por ser o mais básico
dos vetores, porém também são apresentados breves conceitos de vetores recursivos, isto é, listas.
Este documento foi criado no próprio RStudio, por meio do pacote rmarkdown, com base em diver
sas referências sobre a linguagem R, em especial os trabalhos de Wickham (2015a), Peng (2015),
Wickham e Grolemund (2017) e Long e Teetor (2019), assim como a documentação oficial da lin
guagem R (2019b).
• O que é R?
R é um dialeto de S.
S, por sua vez, é uma linguagem de computação desenvolvida nos anos 1970 como um ambiente de
análise estatística, criada com os objetivos de tornar análise de dados mais simples e descomplicada,
além de ser capaz de oferecer funcionalidades mais comumente associadas à uma linguagem de
programação.
• A Filosofia da linguagem S
2.1.1 R
Como dito, R corresponde a um dialeto do S. R é um software livre, o que representa uma de suas
principais características e permite o livre acesso ao código fonte do sistema a qualquer pessoa.
Isto, por sua vez, possibilita as diversas contribuições e melhorias ao seu funcionamento, isto é, o
desenvolvimento de novas funcionalidades por parte dos próprios usuários.
Em comparação a outros pacotes estatísticos, outra vantagem do R é sua capacidade de criar gráficos
com qualidade de publicação. O seu sistema base de gráficos permite o controle de praticamente
todos os aspectos destes objetos.
Atualmente, as semânticas das linguagens R e S não são tão semelhantes. Porém, a filosofia inicial
deste permanece naquele, isto é, a linguagem em R é útil para o manuseio interativo de dados, além
de ser robusta o suficiente para o desenvolvimento de novos instrumentos de análise. Isto permite
aos usuários, que incialmente aplicam as ferramentas existentes na análise de dados, desenvolverem
seus próprios instrumentos, que podem servir à toda comunidade do R.
Como resultado destes fatores, a comunidade de usuários de R é bastante ativa, com contribuições
de pessoas ao redor do mundo, que desenvolvem e ajudam outros indivíduos a resolverem seus
problemas.
2.1.2 O Sistema R
1. O sistema “base” do R, que pode ser baixado no Comprehensive R Archive Network (CRAN);
2. Todo o resto (incluindo os pacotes desenvolvidos por diversas fontes).
As funcionalidades do R e todas as tarefas que podem ser executadas a partir de seu sistema são
divididas em pacotes. O sistema “base” do R, incluído no download do programa no CRAN, contém
o pacote base, necessário para rodar o R e que abrange suas funções mais fundamentais, assim como
outros pacotes, que podem ser vistos aqui.
Contudo, dada a sua natureza de software livre, uma das principais vantagens do R é possibilitar
a expansão das funcionalidades originais de seu programa, a partir de intervenções dos usuários.
Estas intervenções se dão por meio de pacotes criados pelos próprios usuários e submetidos ao
CRAN (e em sites pessoais, que podem ser baixados por meios além do usual, comentado adiante).
2.1.3 RStudio
2.1.4 Considerações
Feita esta recaptulação do R e sua história, no capítulo seguinte são abordados os aspectos básicos
da sintaxe do R e do RStudio, como a inserção de comandos e funções para serem executados,
operadores matemáticos básicos, as referências de documentação da linguagem e como conseguir
ajuda, como utilizar pacotes, etc.
• ' e " (aspas) são caracteres utilizados para escrever elementos (strings) e objetos (vetores de
caracteres) que não são interpretados como números no R (ex.: 'palavra', 'Esta é uma
expressão', "2 é um número", etc);
• : cria sequências de valores;
• <- é o símbolo de designação de objetos.
# Operação de adição
2 + 3
## [1] 5
O número entre colchetes ([1]) não faz parte do objeto em si, apenas revela que este é o primeiro
valor de seu resultado. Alguns comandos geram mais de um valor, de modo que seus resultados
podem encher mais de uma linha no Console. Veremos sobre isso no Capítulo seguinte, sobre
Objetos, especialmente ao criarmos vetores.
O R demanda que sejam inseridos elementos no Console até que uma expressão seja escrita por
completo. Se uma expressão incompleta for inserida, o sinal exibido no Console passa de > para
+, indicando que é necessário completála, ou seja, que você ainda não digitou tudo o que deveria.
Geralmente, isto significa que você esqueceu algum sinal, como fechar as expressões marcadas por
", ' ou ). Insira o caractere faltante ou clique em Esc para abortar a expressão e começar novamente.
Na expressão abaixo, utilizase a função max() para obter o valor máximo de um conjunto de
números contidos entre parênteses.
> max(1,2,3,4,5,5,6
+
Como pode ser visto, é necessário completar a expressão com o ) faltante:
## [1] 6
Além disso, os sinais de operação devem ser escritos ao fim de uma linha, e não no começo.
## [1] -35
Além disso, no quadrante superior direito do RStudio (ao lado de Environment), o histórico de
comandos pode ser acessado pela aba History. O comando history() também acessa esta aba,
especificando a quantidade dos últimos comandos a serem exibidos entre partênteses. Exemplo:
exibir os últimos 10 comandos do histórico:
# Adição: +
5 + 5
## [1] 10
# Subtração: -
5 - 5
## [1] 0
# Multiplicação: *
(3 + 2) * 5
## [1] 25
# Exponenciação: ^ ou **
2 ^ 5
## [1] 32
2 ** 5
## [1] 32
# Divisão: /
20 / 8
## [1] 2.5
## [1] 2
## [1] 4
que pode ser interpretada como: “criase um objeto (no caso um vetor unitário de valor
valor_do_objeto) e a este objeto é atrubuído um nome (nome_do_objeto)”. Ao fazer isso, o
objeto “nome_do_objeto” será salvo no espaço de trabalho atual da memória do R (no painel
“Enviroment”, à direita da tela do RStudio), contendo o valor a ele atribuído pela expressão.
Dica: atalho para o símbolo <-:
Este comando gera <- com espaços imediatamente antes e depois do símbolo, o que facilita e agiliza
a digitação.
Dito isto, iremos começar com o básico: criar um objeto (x) e atribuir a ele um valor númerico
simples (o número 5):
Com isto, o objeto será salvo no Environment. Para que o valor contido no objeto seja exibido,
simplesmente digite o seu nome.4
## [1] 5
Ao escrever uma expressão de designação, para que o valor do objeto seja exibido no Console
juntamente com a expressão, escrevêla entre parênteses:
## [1] 10
O valor contido em um objeto pode ser modificado a qualquer momento. Simplesmente faça outra
operação de designação com o seu nome e um novo valor. Exemplo:
4
A função print() pode ser utilizada para este propósito, mas não é usual, já que é mais fácil simplesmente digitar o
nome do objeto. Geralmente, esta função é utilizada na criação de outras funções, quando há a necessidade explícita
de exibir o objeto.
## [1] 9
• Letras
• Números (dígitos)
• _ (underline)
• . (ponto)
• _ (underline)
• Número (dígito)
• . seguido de um dígito
Dica: dê nomes claros e descritivos aos objetos (ex.: microdados_pnad_2010, para uma base de
dados contendo os microdados da PNAD de 2010; vetor_anos_1990_2010, para um vetor que
contém os anos dentro do intervalo desejado, etc).
OBS.: a linguagem R é sensível a letras Maiúsculas e minúsculas. Assim, ao designar um objeto,
a forma com que o seu nome é escrito importa.
Objeto <- 10 ^ 2
Objeto
## [1] 100
objeto <- 2 + 2
objeto
## [1] 4
Como visto, Objeto e objeto contêm valores distintos e representam objetos distintos.
Ao designar valores aos objetos, podemos utilizálos para diversos propósitos. Como exemplo,
supomos que desejamos contar a quantidade total de horas/aula deste curso e a quantidade de ho
ras/aula concluídas até o momento:
Ao criar estes objetos, podemos obter a quantidade de horas/aula restantes até a conclusão do curso:
## [1] 30
## [1] 30
Por exemplo, a função log() (que será mencionada posteriormente) possui dois argumentos: x
representa os dados e base a base em que o logaritmo é computado.
Como mencionado anteriormente, o sistema base do R possui um conjunto de funções, capazes de
desempenhar as funcionalidades mais fundamentais da linguagem. Podemos, por exemplo, obter o
valor máximo de um conjunto de números, com a função max().
## [1] 100
OBS.:: Em grande parte das funções, os argumentos não precisam ser especificados por nome. Ou
seja, pode se utilizar uma função da seguinte maneira:
exemplo_função(valor1, valor2)
o que irá executar a função exemplo_função passando os valores valor1 e valor2 aos argumentos
argumento1 e argumento2, respectivamente. Para “passar” um argumento, respeitase a ordem
dos argumentos encontrados na documentação da função.
O exemplo abaixo contém uma função para inserir dados de uma planilha .csv no R, com e sem a
especificação de seu primeiro argumento, file =.
• Dica: especificar os argumentos das funções ajuda a compreensão do código para outros
usuários. Em um momento inicial, recomendase adotar esta prática.
A seção de ajuda interna ao RStudio pode ser acessada pelo comando help(). Com ele, pode se
consultar a definição e o funcionamento de uma função, por exemplo. Para isto, deve se escrever
help(nome_da_função)
no Console. No RStudio, este comando abre a aba Help, no painel direito inferior do programa.
Dica: O comando ? é um atalho para o comando help(). Digitar
? + nome_da_função
para obter a ajuda do R, igualmente à help(nome_da_função).
Exemplo: Obter a ajuda da função max()
# Usando `help()`
help(max)
# Usando `?`
?max
Dica: use o comando args() para obter os argumentos de uma função. Use example() para ver
os exemplos de uso de uma função encontrados na documentação do próprio R.
Como vemos, a função max() contém o argumento especial ‘...’, o que significa que podemos in
cluir uma quantidade qualquer de valores numéricos dentro de seus parênteses, para serem avaliados
(i.e., para se definir qual possui o maior valor).
Além da ajuda interna, outras fontes de ajuda para introduzir e aprofundar os conhecimentos da
linguagem são a documentação oficial do R e referências produzidas por autores/usuários (livros
texto, cursos online, etc). Estes recursos servem de auxílio na solução de problemas do diaadia e
são extremamente úteis na consulta de dúvidas.
• Cursos e materiais
• Livrostexto
– R for Data Science: livro referência sobre a utilização de R para Ciência de Dados
(contendo os principais pacotes utilizados neste curso);
– R Programming for Data Science: livro sobre os fundamentos do R sob a perspectiva
da Ciência de Dados;
– R Cookbook: guia de “receitas” solução de problemas no R. Indicado para qualquer
usuário, já que o nível de dificuldade das tarefas aumenta ao longo do livro, começando
dos problemas mais básicos até os mais complexos;
– HandsOn Programming With R: guia prático para aprender a programar em R;
– R Graphics Cookbok: guia de receitas (semelhante ao R Cookbook) de gráficos no R;
– Efficient R Programming: guia avançado para tornar a programação e a escrita de có
digos em R mais eficiente;
– Advanced R: guia avançado para usuários de R entenderem melhor o funcionamento da
linguagem e escreverem códigos mais eficientes.
• Páginas oficiais
– RStudio Cheatsheets
Como usuário do R, é imperativo tornarse familiarizado com os recursos existentes na internet para
a solução de dúvidas. Por ser um software livre, uma das principais características do R é a interação
entre os seus usuários na comunidade. O canal mais utilizado de dúvidas é o Stackoverflow, uma
Como exemplo de aprender a ler a documentação de uma função e utilizála, iremos arredondar
valores. Primeiramente, iremos partir da função round(). Assim, obter a ajuda interna do RStudio,
por meio do comando help().
O comando acima nos leva à página interna de ajuda de funções utilizadas para arredondar valores
númericos (Rounding of Numbers). São apresentadas as seguintes funções:
Pela descrição da função round(), vemos que ela arredonda os valores do primeiro argumento à
quantidade de casas decimais especificadas, sendo o padrão (default) igual a 0.5 Para ver os seus
argumentos, podemos utilizar o comando args(), como visto anteriormente.
5
“round rounds the values in its first argument to the specified number of decimal places (default 0).”.
O argumento x indica o vetor numérico a ser arredondado. O argumento digits, para a função
round(), indica o número de casas decimais que será utilizada no resultado final.
Dito isto, podemos arredondar o número 3.1455.
## [1] 3
## [1] 3.15
OBS.: Como visto, no R, as casas decimais dos números reais são especificadas por . (ponto), e
não por , (vírgula), como em português. Mais detalhes sobre isto, na seção Numéricos (Numeric),
no capítulo seguinte.
Além disso, nos detalhes da documentação da função (Details), vemos que ao arredondar o valor 5,
a função round() o faz em direção ao número par (even digit). Isto pode ser visto pelas aplicações
abaixo.
## [1] 0
round(1.5)
## [1] 2
round(4.115, digits = 2)
## [1] 4.12
Além disso, podese arredondar para potências de dez, especificadas no argumento ‘digits =’
como um número negativo. Por exemplo, round(x, digits = -2) arredonda para a centena
mais próxima.
## [1] 100
## [1] 10
Podemos explorar o comportamento das outras funções (ceiling() e floor()) testando os resul
tados obtidos para os números 0.05, 1.1 e 1.5.
# Ceiling
ceiling(0.05)
## [1] 1
ceiling(1.5)
## [1] 2
ceiling(-1.1)
## [1] -1
# Floor
floor(0.05)
## [1] 0
floor(1.5)
## [1] 1
floor(-1.1)
## [1] -2
Podemos verificar quais objetos estão salvos no Enviroment, utilizando a função ls().
# Listando objetos presentes no Environment
ls()
Por meio da função rm(), podemos remover objetos do Environment. Isto é importante para deixar
o espaço de trabalho mais organizado e “limpar” a memória do R, principalmente em um nova seção
de análise de dados, um projeto distinto, etc. Para remover um objeto, simplesmente incluir o seu
nome dentro dos argumentos da função rm():
# Remover os objetos 'objeto' e 'Objeto'
rm(objeto, Objeto)
Feito isto, supomos que, por descuido, tentemos remover novamente o objeto objeto do Environ
ment.
• Fazer uma pesquisa descrevendo o problema em questão. Por exemplo: ‘r how remove object
environment’, indicando que procuramos alguma página relativa ao R sobre como remover
objetos do Environment.
A resposta mais votada para a questão exposta acima apresenta a razão do erro ter ocorrido (i.e., o
R não conseguiu encontrar a variável mencionada no comando) além de modos para checar se uma
variável existe (utilizando a função ls(), apresentada anteriomente, e outra, exists()), possíveis
razões para outros erros desta natureza, referências para consultas mais avançadas, na documentação
do R e no livro Advanced R (citado nas referências), entre outros aspectos.
Como visto, portanto, é fundamental acostumarse a buscar respostas na internet aos problemas
encontrados no R. Além disso, só tentando executar os códigos, implementar as funções, etc, que
aprendemos a utilizar a linguagem.
2.2.6 Scripts
Um Script é um arquivo que contém um conjunto de códigos e comandos que podem ser acessados
e excecutados facilmente, tornando o fluxo de trabalho no RStudio mais eficiente. Ao utilizar o
RStudio, os códigos contidos nos scripts podem ser executados individualmente ou em conjunto.
Para criar um script no RStudio, clicar em File → New File → R Script, como na imagem abaixo,
ou utilizar o atalho Ctrl + Shift + N.
Com isso, o quadrante esquerdo do RStudio será dividido verticalmente em dois: a parte superior
comporta o editor de scripts e a inferior o Console.
Assim como no Console, o símbolo # marca o início de um comentário em um script. Tudo a sua
direita, portanto, será ignorado pelo R ao executar um comando. Se posicionarmos o cursor em
uma linha iniciada por um comentário, o R irá ignorála e executar a linha subsequente que contém
um código executável.
Diferentemente do Console, no Script, a tecla Enter não executa um comando, apenas quebra uma
linha (i.e., adiciona um parágrafo no Script). Isto é bastante útil para comandos ou funções longas,
que dependem de muitos argumentos, pois permite tornar o código mais legível para outros usuários
(afinal, os códigos não devem ser apenas avaliados e executados pelo computador, como também
entendidos pelos outros usuários que forem utilizálos).
A maneira mais eficiente de executar um comando individualmente é usar o atalho Ctrl + Enter,
que executa a linha ou seleção corrente. Para tanto, posicione o cursor em qualquer posição da
linha desejada e pressione o atalho (Ctrl + Enter). O mesmo pode ser atingido pelo ícone Run no
quadrante do Script.
Ao executar um comando do script, o comando e seu respectivo resultado serão exibidos no Console.
Se houver uma necessidade de exectuar um comando que se estende por várias linhas, você pode
posicionar o cursor em apenas uma delas e pressionar Ctrl + Enter ou selecionar todas as linhas
e fazer o mesmo.
# Criar o objeto `z` (soma de 1, 2 e 3), em um comando que se estende por três linhas do script
z <- 1 +
2 +
3
z
## [1] 6
Para executar todos os comandos de um script, clicar no ícone Source ou digitar o atalho Ctrl +
Shift + S.
Para que os resultados de execução de um script inteiro sejam exibidos no Console, clicar na seta
ao lado de Source e clicar em Source with echo ou usar o atalho Ctrl + Shift + Enter.
Figura 2.11: Run: resultado após executar o comando das linhas 5, 6 e 7 do Script
A grande vantagem de utilizar Scripts é salvar a forma com que se obtém os resultados desejados,
no lugar dos própios resultados. Ou seja, em muitas situações, é prático salvar o Script (contendo
os códigos necessários para realizar tarefas específicas) no lugar de salvar os objetos contidos no
Environment.
Para salvar um script, clicar em File → Save As…, escolhendo o diretório em que o arquivo será
guardado. Uma vez definido o local e escolhido o nome do script, clicar em File → Save ou utilizar
o atalho Ctrl + S para salvar o arquivo corrente. O script possui a extensão .R e pode ser aberto
por editores de texto padrão (Bloco de Notas/Notepad, Sublime Text, etc).
2.2.7 Pacotes
Como destacado anteriormente, o R possui um conjunto de funções incluídas na base de seu sis
tema, que são carregadas automaticamente no R/RStudio e que podem ser executadas sem nenhum
requerimento adicional. Contudo, uma das principais características do R é a interação entre os
usuários de sua comunidade. Assim, os próprios usuários podem desenvolver novas funções para
desempenhar diferentes funcionalidades no R e compartilhálas com outros pessoas. Os Pacotes
• Pacotes instalados
• Pacotes carregados
Para obter uma lista dos pacotes carregados na presente sessão, executar a função search() sem
argumentos:
• OBS.: Alguns pacotes, apesar de estarem presentes nas versões base do R e RStudio (ou seja,
que são baixadas junto com os programas) não são carregados automaticamente ao iniciar o
software. Assim, é preciso carregálos, da mesma forma que pacotes baixados, pelo comando
library("nome_do_pacote") para acessar seus conteúdos.
A grande maioria dos pacotes está em constante transformação, visto que os desenvolvedores sem
pre procuram novas maneiras de deixálos mais eficientes ou de resolver problemas encontrados
pelos usuários.7 Assim, é necessário atualizálos periodicamente, para obter as funções mais atuais
e, consequentemente, com menor chance de apresentarem erros. Para atualizar um pacote, simples
mente rode o comando de instalação de pacotes (install.packages("nome_do_pacote")) ou
acesse o menu Tools → Check for Packages Updates… no RStudio, como na imagem abaixo:
Para obter ajuda sobre um pacote, são utilizados dois comandos principais:
O primeiro abre a janela de ajuda do pacote no próprio RStudio, contendo seu autor e links úteis so
bre a sua utilização. Como exemplo, a janela de ajuda obtida após package?tidyverse apresenta,
entre outras coisas, um link bastante útil sobre o pacote e seu conjunto de pacotes, com detalhamento
das funções, exemplos de suas utilizações, etc.
O comando help(package = "nome_do_pacote") exibe o manual e referência do pacote, isto
é, a página de ajuda de todas as funções de um pacote no próprio RStudio, proveviente de sua
7
Algumas funções, ou até mesmo pacotes, são descontinuados ou não são atualizados pelos desenvolvedors. Desta
forma, estas funcões podem ser removidas dos pacotes ou os pacotes passam a poder ser executados somente em
versões específicas dos pacotes ou do R. Assim, aconselhase acompanhar as páginas de desenvolvimento dos pacotes
ou de documentação oficial do R.
documentação oficial. Como exemplo, na figura abaixo é exibida a janela obtida após o comando
help(package = "readr"), sobre a ajuda do pacote readr, usado posteriormente neste curso
para a importação de dados no R.
Além disso, é usual procurar no Google sobre a documentação oficial do pacote no CRAN, em que
podem ser obtidos detalhes de funcionamento das funções, exemplos, etc. Por exemplo, pode se
procurar sobre o pacote readr, por meio da busca no google para r cran package readr.
A primeira página dos resultados da busca corresponde à página de documentação oficial do
pacote no CRAN. No item Reference manual em Downloads, pode ser obtido o manual de
referência do pacote em .pdf. Este manual é o mesmo obtido pelo comando help(package =
"nome_do_pacote").
Adicionalmente, alguns pacotes incluem documentos adicionais, contidos nos arquivos baixados
em suas instalações na máquina. Estes documentos, chamados de vignettes (vinhetas), auxiliam
no aprendizado das funções de um pacote, contendo introduções e tutoriais. Se um pacote
possuir esta documentação, a sua página de help (que pode ser acessada por help(package =
'nome_do_pacote)) irá exibíla.
A visualização de vinhetas é obtida pela função vignette(). Os comandos abaixo mostram como
visualizar uma lista de todas as vinhetas contidas no computador (i.e. dos pacotes instalados na
máquina) e de todas vinhetas de um pacote específico. Esta lista será exibida no quadrante superior
esquerdo, ao lado do script corrente.
# Listar todas as vinhetas do computador
vignette()
# Listar todas as vinhetas de um pacote
vignette(package = "nome_do_pacote")
Cada vinheta possui um nome. Para acessála, digitar o comando abaixo, que irá abrir a aba Help
no quadrante direito inferior, com os seus conteúdos.
# Acessar uma vinheta
vignette("nome_da_vinheta")
Como mencionado, em linhas gerais, para acessar os conteúdos de um pacote (funções, documenta
ção, base de dados, etc), ele deve ser carregado na sessão presente do R (na memória do programa).
Contudo, em alguns casos, desejase utilizar apenas uma função de um pacote inteiro em uma de
terminada sessão do R. Assim, há a possibilidade de não carregar o pacote inteiro, mas executar a
função específica, por meio da sintaxe:
O código acima corresponde ao uso de uma função específica de um pacote, sem que ele seja car
regado na sessão presente do R.
ATENÇÃO: para que o comando acima seja executado, o pacote deve estar instalado no com
putador (por meio do comando install.packages("nome_do_pacote"), apresentado anterior
mente).
O comando acima também é útil para situações em que funções de pacotes distintos, instalados e
carregados em uma mesma sessão, possuem o mesmo nome (ex.: funções data.table::dcast()
e reshape2::dcast()).
Duas dicas são destacadas para um fluxo de trabalho mais eficiente na organização de scripts e
utilização de pacotes:
Esta prática é recomendada, já que garante que todas as dependências necessárias para executar
os códigos estarão carregadas na hora de executálas, como destacado em Gillespie and Lovelace
(2017).
Gillespie and Lovelace (2017) recomendam designar um vetor contendo todos os pacotes que serão
carregados em uma sessão/script. Desta forma, o processo de carregar os pacotes (e instalar, se
necessário) será mais eficiente (i.e., menor quantidade de linhas para ser executado), além de per
mitir uma fácil referência a estes pacotes. Para utilizar esta prática, são utilizados conhecimentos
de vetores (comentados no capítulo seguinte do curso) e uma função da família apply (lapply()),
que foge do escopo deste curso. Porém, os comandos abaixo podem ser executados sem problemas
nos scripts e o funcionamento dos vetores será explicado posteriormente.
Dado que agora temos as principais referências às dúvidas à nossa disposição, assim como noções
básicas do funcionamento do R, o capítulo a seguir apresenta mais detalhes sobre os objetos no R,
em especial a sua principal família: vetores.
• Tipo (type), propriedade do vetor inteiro, que pode ser entendida como a forma de organiza
ção de dados mais complexa que um vetor pode conter como um de seus valores. Podemos
visualizar o tipo de um objeto pela função typeof():
## [1] "double"
## [1] 1
Em essência, a diferença entre vetores atômicos e listas reside no tipo (type) de elemento que cada
um é capaz de armazenar. Em vetores atômicos, o tipo é uma propriedade do vetor inteiro, e não
de um elemento individual do vetor. Assim, enquanto os vetores atômicos são homogêneos, isto é,
cada vetor pode conter somente elementos de um mesmo tipo, as listas podem ser heterogêneas,
ou seja, podem conter elementos de diferentes tipos.
O diagrama abaixo, de Wickham (2015a), mostra os principais vetores (atômicos e listas).
Iremos começar com os vetores atômicos, por ser o objeto mais básico empregado nas aplicações
fundamentais do R.
Para este capítulo, serão utilizadas algumas funcões do pacote purrr. Desta forma, instalar e car
regar o pacote tidyverse, que contém o pacote purrr, seguindo os comandos apresentados ante
riormente.
# Instalar pacote
install.packages('tidyverse')
# Carregar pacote
library('tidyverse')
5. raw
6. complex
Neste curso, será dado destaque às quatro primeiras categorias (character, integer, numeric e logi
cal), já que raw e complex não são comumente empregados em análises de dados. Os principais
tipos de vetores atômicos são apresentados na figura abaixo.
A figura acima indica outro conceito de categorização dos objetos: o modo (mode). O modo de
um objeto é determinado de acordo com sua estrutura básica e representa uma classificação mutu
almente exclusiva dos objetos, isto é, cada objeto possui um, e apenas um, modo. Existem quatro
modos de vetores atômicos: logical, numeric, character e complex. Como visto, os vetores de modo
numeric (numérico) são compostos por dois tipos: integer (números inteiros) e double (números
reais). De maneira sintética, o modo e o tipo de um objeto podem ser vistos como o tipo de dados
mais complexo que um vetor atômico no R pode conter em seus valores. Mais detalhes podem ser
obtidos aqui.
Dito isto, lembramos que, até este momento, já criamos vetores neste curso. Os objetos
horas_aula_total, horas_aula_concluidas e horas_aula_restantes, por exemplo, são
vetores que contêm apenas um elemento numérico, isto é, são vetores unitários de modo numérico.
## [1] 1 2 3 4 5
Ao criar um vetor com a função c() a partir de outros vetores atômicos, o resultado é outro vetor
atômico, isto é, a estrutura é simplificada para apenas um vetor.
# Criando um vetor atômico a partir de outros vetores atômicos
(vetor_atomico <- c(c(0, 10, 20, 30), c(1,2)))
## [1] 0 10 20 30 1 2
2.3.3 Sequências
2.3.3.1 Sequências simples (intervalo unitário)
O caractere : permite criar sequências de números inteiros, com um intervalo unitário, isto é, de 1
em 1.
# Sequência de 0 até 50, de 1 em 1
(0:50)
## [1] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
## [26] 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
## [51] 50
Como visto, o resultado do comando 0:50 é maior do que o tamanho do Console, o que faz com que
sejam exibidos números entre colchetes ([1], [26] e [51], no exemplo), indicando qual a posição
do número dentro do vetor.
# Criar sequência do maior para o menor valor
(30:1)
## [1] 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6
## [26] 5 4 3 2 1
A função seq() permite especificar o valor que será somado à cada membro da sequência. Para
isto, especifique o valor somado no argumento by =. Além disso, pode ser especificado o tamanho
da sequência (quantidade de componentes do vetor), sem que seja especificado a quantia que será
somada, por meio do argumento length.out =.
## [1] 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30
## [1] 0 3 6 9 12 15 18 21 24 27 30
A função rep() permite criar sequências de valores repetidos. Para isto, utilizar o argumento times
=.
## [1] 14 14 14 14 14 14 14 14 14 14
Como visto na Figura 18, em R, os vetores numéricos (Numeric vectors), compostos por valores
numéricos, são divididos em Integer e Double (números inteiros e reais, respectivamente). A função
typeof() permite descobrir o tipo do vetor.
## [1] "double"
O resultado acima mostra que ao criar um vetor numérico, o R assume, por padrão, números
reais (double).
Desta forma, para criar um vetor de números inteiros (tipo integer), devemos inserir o caractere L
logo após o número.
## [1] "integer"
## [1] 1
OBS.2: Em R, os números reais (doubles) são aproximações, dado que o computador pode alo
car uma quantidade fixa e limitada de memória para cada número no R. Desta forma, segundo
Grolemund (2014), em R, os números reais são precisos até 15 dígitos decimais (ou 16 dígitos sig
nificativos). Podemos verificar isto comparando a subtração do quadrado da raiz quadrada de 2 (o
que, em teoria, seria o próprio número 2) pelo número 2.
## [1] 0.0000000000000004440892
## [1] 0
Como visto, a raiz quadrada de 2 (raiz_2) não pode ser expressa exatamente em 16 dígitos sig
nificativos. Como resultado, este valor é arredondado pelo R, o que faz com que a subtração do
quadrado da raiz de 2 (quadrado_raiz_2) por 2 seja algo bastante próximo, porém não exatamente,
de zero.
Em conclusão, atenção ao utilizar números reais nos cálculos. À frente entraremos em detalhes
com os operadores lógicos e como comparar valores, na Subseção Comparando Vetores.
OBS.3: Os objetos numéricos possuem caracteres especiais, para especificar algumas situações
específicas.
• Doubles possuem quatro valores especiais: NA, NAN, Inf e -Inf. De maneira superficial,
seus signficados são os seguintes:
• Integers possuem apenas um valor especial: NA, para indicar valores faltantes.
Os vetores lógicos são o tipo mais simples de vetores atômicos, por poderem conter apenas três
valores possíveis: TRUE, FALSE e NA. Estes valores representam informações lógicas, que podem
ser utilizadas para comparações e para determinar a veracidade de operações, entre outras apli
cações. Os valores/operadores lógicos, divididos entre “Verdadeiro” e “Falso”, são chamados de
valores/operadores booleanos (Boolean values). Toda vez que TRUE ou FALSE for digitado em caixa
alta no R, o R irá interpretálo como um dado de tipo lógico. Além disso, T e F são abreviações de
TRUE e FALSE, respectivamente.
# Tipo do vetor
typeof(vetor_logico)
## [1] "logical"
## [1] "logical"
# Vetor de caracteres
(vetor_caracteres <- c("Este", "é", "um vetor atômico contendo caracteres"))
## [1] "Este"
## [2] "é"
## [3] "um vetor atômico contendo caracteres"
# Tipo do vetor
typeof(vetor_caracteres)
## [1] "character"
Lembrando que as strings podem conter mais do que letras, i.e., podem ser compostos de números,
símbolos, etc.
## [1] "double"
typeof('1')
## [1] "character"
typeof('one')
## [1] "character"
x <- c(-5:20)
# Função `str()`
str(x)
Como visto, a função str() informa que o objeto x é um vetor numérico de numéros inteiros
(integer), composto por 26 elementos (exibindo os 10 primeiros elementos no Console).
Em R, as operações matemáticas básicas podem ser utilizadas em pares de vetores, de modo que os
operadores são aplicados aos elementos correspondentes de cada vetor. Assim, em uma adição entre
vetores (vetor1 e vetor2), o primeiro elemento do vetor1 será somado ao primeiro elemento do
vetor2, o segundo elemento do vetor1 ao segundo elemento do vetor2, etc. Abaixo, um exemplo
de operações matemáticas em vetores de mesmo comprimento.
## [1] 7 9 11 13 15
vetor1 - vetor2
## [1] -5 -5 -5 -5 -5
vetor1 * vetor2
## [1] 6 14 24 36 50
vetor1 / vetor2
length(vetor1)
## [1] 5
length(vetor1 + vetor2)
## [1] 5
vetor1 * 0.5
O processo de reciclagem dos vetores ocorre sem avisos no R em situações em que o comprimento
do maior vetor é um múltiplo inteiro do comprimento do menor vetor. Nas situações em que isto
não ocorre, ao realizar a operação matemática, será exibido um aviso no Console.
## [1] 10 20 30 40 50 60 70 80 90 100
## [1] 11 22 31 42 51 62 71 82 91 102
## [1] 11 22 33 41 52 63 71 82 93 101
Por conta desta regra, devese estar bastante atento ao realizar operações com vetores de compri
mentos distintos.
De maneira análoga aos operadores matemáticos, podemos realizar operações relacionais e lógicas
entre os vetores. Em outras palavras, podemos comparar dois vetores, testando a veracidade de
algumas afirmações, por exemplo, se o objeto1 é igual ao objeto2, se o objeto1 é maior do que
o objeto2, etc. Os seguintes caracteres são utilizados como operadores relacionais e lógicos entre
vetores:
x <- 1
y <- 5
z <- 5
w <- 1:10
# Operações relacionais e lógicas
x > y
## [1] FALSE
x < y
## [1] TRUE
x != y
## [1] TRUE
y == z
## [1] TRUE
z | x <= y
## [1] TRUE
z & y <= x
## [1] FALSE
isTRUE(x * 5 == y)
## [1] TRUE
!(x < y)
## [1] FALSE
x %in% w
## [1] TRUE
## [1] TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
vetor_comparacao1 > 8
## [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE
## [1] TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE TRUE TRUE
vetor_comparacao1 %% 3 == 0
## [1] FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE FALSE
## [1] FALSE FALSE FALSE FALSE FALSE TRUE TRUE TRUE TRUE TRUE
Os operadores xor(), any() e all() também podem ser utilizadas em operações relacionais, para
determinar se exatamente uma, pelo menos uma ou todas as comparações são verdadeiras, respec
tivamente. O primeiro retorna TRUE se exatamente uma das condições for veradeira. O segundo
retorna TRUE se pelo menos uma das condições for verdadeira. O terceiro retorna TRUE se todos as
condições forem verdadeiras.
v <- 1:4
# Retorna TRUE se exatamente uma das condições for verdadeira
xor(1 < 2, 1 < 3)
## [1] FALSE
## [1] TRUE
## [1] FALSE
Dica: Evitar utilizar == para checar os valores especiais de objetos numéricos (NAN, NA, Inf e -Inf).
Utilizar as funções is.finite(), is.infinite(), is.na() e is.nan() no lugar. Além disso,
atentar para o fato de que a função is.na() aponta TRUE tanto para NA quanto para NAN.
As seguintes funções executam operações matemáticas bastante úteis em análises de dados, como
a obtenção da média, da mediana, do desviopadrão, etc.
Função Operação
mean() Média
median() Mediana
sqrt() Raiz quadrada
log() Logarítimo
sd() Desviopadrão
abs() Valor absoluto
sum() Soma
## [1] 0 2 4 6 8 10 12 14 16
# Média do vetor
mean(vetor5)
## [1] 8
# Mediana do vetor
median(vetor5)
## [1] 8
## [1] 5.477226
## [1] 3 2 1 0 1 2 3
## [1] 72
Além de tipo (type) e comprimento (length), que podem ser conferidos pelas funções typeof() e
length(), mencionados anteriormente, os vetores possuem uma propriedade adicional: os atribu
tos (attributes). Os atributos representam informações suplementares sobre os dados (metadados,
i.e., dados sobre os dados), que podem ser ligadas aos objetos. Os atribtuos modificam aspectos
das estruturas dos vetores, atribuem características específicas a seus elementos e permitem a reali
zação de operações adicionais com os vetores. Desta forma, os metadados são úteis na descrição e
caracterização dos objetos (por exemplo, permitem nomear as colunas de uma base de dados, para
identificar quais dados estão contidos em cada uma delas). Por meio dos atributos, são criados ou
tros tipos de vetores, extremamente úteis em análises de dados e no próprio uso do R, como fatores
(factors) e datas e horasdata (dates e datetimes).10
Os principais atributos empregados nas funcionalidades fundamentais do R são:
Os atributos individuais de um objeto podem ser acessados ou modificados pela função attr(),
enquanto todos os atributos de um objeto podem ser acessados ou modificados pela função
attributes(). Caso o objeto não possua nenhum atributo, isto será indicado pelo resultado
da função attributes(nome_do_objeto), ao retornar o valor NULL (explicado na subseção
seguinte).
A função names() permite acessar os nomes de um vetor, assim como designálos (se eles não
existirem) ou modificálos (se já existirem).
Dito isto, em linhas gerais, existem três maneiras principais de nomear os elementos de um vetor
por meio das funções da base do R:
# Ao criá-lo, acrescentando os nomes no vetor como abaixo
x <- c(a = 1, b = 2, c = 3)
x
## a b c
## 1 2 3
## a b c
## 1 2 3
Para facilitar a seleção de elementos nomeados em vetores, seus nomes devem ser únicos e não
faltantes.
Para remover os nomes de um vetor, utilizar a função unname() ou a própria função names(), com
o objeto NULL (comentado na seção seguinte):
# Função `unname()`
x <- unname(x)
# Função `names()`
names(y) <- NULL
Ao adicionar o atributo dim a um vetor, é possível criar uma matriz (matrix). Uma matriz representa
um vetor de duas dimensões11 . Vale lembrar, portanto, que o tipo de um matriz é uma propriedade
de todo o vetor, de modo que seus elementos individuais não possuem tipos diferentes do restante
da matriz.
A quantidade de colunas de uma matriz é obtida por ncol(nome_da_matriz), enquanto a quan
tidade de linhas é obtida por nrow(nome_da_matriz). As matrizes podem ser criadas com o co
mando matrix() ou ao definir um vetor com as proporções desejadas no argumento dim.
## [,1] [,2]
## [1,] 1 5
## [2,] 2 6
## [3,] 3 7
## [4,] 4 8
## [,1] [,2]
## [1,] 1 4
## [2,] 2 5
## [3,] 3 6
11
Podem ser criados vetores com mais dimensões (arrays), mas não serão mencionados neste curso.
## [,1] [,2]
## [1,] 10 90
## [2,] 40 160
## [,1] [,2]
## [1,] 10 10
## [2,] 10 10
## [,1] [,2]
## [1,] 70 150
## [2,] 100 220
# Classe t_w
class(t_w)
# Tipo t_w
typeof(t_w)
## [1] "integer"
Observase que a função t() retorna, necessariamente, um objeto de classe matrix e de tipo igual
ao objeto inicial (no caso, integer).
Em geral, em análise de dados, os objetos de classe matrix não são muito utilizados, visto que,
assim como vetores, estes objetos podem conter apenas um tipo de objeto. Como será visto ao
longo do curso, é costume utilizar as data.frames, pela possibilidade de serem heterogêneas, isto é,
por poderem conter objetos de diferentes tipos, o que é bastante útil em Ciência de Dados.
Em R, a classificação dos objetos em classes (class) distintas determina como funções (genéricas)
operam com eles, isto é, representa diferenças nas aplicações que podem ser feitas com cada um
deles. Por exemplo, operações matemáticas não podem ser realizadas com vetores de caracteres
(character) ou fatores (factors). Esta característica é bastante relevante, especialmente quando al
gumas funções possuem comportamentos distintos para diferentes classes de objetos. Mais adiante,
iremos destacar as conversões automáticas de classes de objetos e como realizar, explicitamente, a
conversão para a classe desejada, assim como alguns problemas que advêm deste processo.
Para verificar a classe de um objeto, utilizar a função class().
# Verificar a classe de um objeto
class(horas_aula_concluidas)
## [1] "numeric"
2.3.9 NULL
O objeto NULL indica a ausência de um objeto. Geralmente associado aos vetores, é comumente
interpretado como um vetor de comprimento zero, pelo seu comportamento. Esta interpretação,
contudo, está equivocada segundo a documentação do R (2019b). O objeto NULL é um tipo de objeto
especial e corresponde a um objeto único, de modo que todas as instâncias que fazem menção a ele
se referem ao mesmo objeto. O objeto NULL não possui tipo, atributos ou propriedades modificáveis.
Segundo R Core Team (2019b), ele não deve ser confundido com um vetor ou lista de tamanho zero,
apesar ser entendido desta maneira por diversas referências. Para testar para NULL, utilizar a função
is.null().
O diagrama abaixo, de Wickham (2015a), mostra os principais tipos de vetores e o objeto NULL:
Em R, quando diferentes tipos de objetos são inseridos em um mesmo vetor, eles são convertidos
(coerced). Isto ocorre, uma vez que o tipo é uma propriedade do objeto inteiro, e não de seus
elementos individuais. Ao agrupar elementos de tipos diferentes em um mesmo vetor atômico (por
meio da função c(), por exemplo), há uma conversão automática dos objetos para um mesmo tipo
(coerção implícita). Nela, sempre é preservado o tipo de maior complexidade. A ordem crescente
de complexidade dos tipos de objetos é a seguinte.
Logical → Integer → Double → Character
Assim, ao combinar um vetor de caracteres e outro de números inteiros, obtemos um caractere, por
exemplo. Podemos conferir os tipos dos vetores misturado*, criados logo acima.
## [1] "integer"
## [1] "double"
## [1] "character"
Além da função typeof(), podemos utilizar as funções is_*(), do pacote purrr, para verificar
os tipos (*) dos objetos. Cada função fornece um resultado TRUE para os tipos de objetos marcados
com um x no quadro abaixo, de Wickham e Grolemund (2017), enquanto os objetos sem marcação
resultam em um resultado FALSE.
## [1] TRUE
is_integer(misturado2)
## [1] FALSE
is_double(misturado2)
## [1] TRUE
is_character(misturado1)
## [1] FALSE
is_character(misturado3)
## [1] TRUE
Além disso, cada predicado possui a função is_scalar_*() para identifcar se determinado vetor,
do tipo (*) especificado, possui comprimento (length) igual a 1.
OBS.: Analogamente às funções is_*(), do pacote purrr, as funções is.*(), da base do R,
também são empregadas para determinar o tipo de um objeto. Elas também geram um vetor lógico
a partir de sua utilização. Contudo, segundo Wickham e Grolemund (2017) e Wickham (2015a), é
recomendado evitar o uso destas funções para verificar os tipos dos objetos, em função de resultados
que podem ser surpreendentes. Para mais detalhes, consultar Wickham e Grolemund (2017) e as
documentações do R e das funções, caso seja necessário.
OBS.2: Quando os objetos lógicos (TRUE e FALSE) são convertidos para numéricos, eles assumem
dois valores: 1 e 0, respectivamente. Podemos observar isto no objeto misturado1, que criamos
anteriormente, uma vez que, seguindo a ordem de complexidade apresentada, converteu, implicita
mente, os elementos lógicos para integer.
## [1] 1 0 10 20
# Outro exemplo
c(TRUE, TRUE, FALSE, 1.1, 1.2, 1.3)
Isto pode ser útil em funções matemáticas, que convertem automaticamente objetos lógicos para
numéricos. A partir desta funcionalidade, podemos obter o total ou a média de valores TRUE em um
vetor, por exemplo:
## [1] FALSE FALSE FALSE TRUE TRUE TRUE TRUE TRUE FALSE TRUE
## [1] 6
# Proporção de TRUEs
mean(w)
## [1] 0.6
Na subseção seguinte, explicamos o que ocorre com a situação inversa, isto é, quando convertemos
um objeto numérico para lógico.
Além das conversões automáticas (implícitas) que acontecem com algumas funções, é possível
converter explicitamente um objeto para a classe desejada. As funções as.*() fazem justamente
isto, convertendo o objeto para a classe (*) em questão.
x <- 0:10
class(x)
## [1] "integer"
## [1] TRUE
## [1] FALSE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
is_logical(x_logicos)
## [1] TRUE
## [1] "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
class(x_caractere)
## [1] "character"
Como visto, quando convertemos um objeto numérico para lógico, o valor 0 é convertido para
FALSE, enquanto os valores restantes se tornam TRUE.
As coerções explícitas podem gerar erros supostamente inesperados, sendo fontes de frustração. Em
especial, a conversão de vetores de caracteres para outros tipos podem ser problemáticas. Nestes
casos, são exibidas advertências e gerados valores faltantes (NA), no lugar dos valores que não podem
ser convertidos de maneira apropriada.
## [1] "-10" "-9" "-8" "-7" "-6" "-5" "-4" "-3" "-2" "-1" "0" "1"
## [13] "a" "b"
## [1] NA NA NA NA NA NA NA NA NA NA NA NA NA NA
## [1] 0 1 1 NA
Como visto, no segundo exemplo, o caractere 'a' não consegue ser convertido para um número
inteiro, tornandose o valor faltante, NA.
Considerando um vetor x, criado de forma que cada dígito após a casa decimal de cada elemento
representa a posição original deste elemento no vetor (ex.: 3.1 indica que o número é o primeiro
elemento do vetor):
12
A seção sobre listas contém maneiras de indexar e selecionar elementos de listas e de base de dados, com suas
particularidades.
• [[
## [1] 3.1
# Estrutura
str(x[[1]])
## num 3.1
## [1] 2.5
• [
Dito isto, a utilização de [ para selecionar os elementos de x pode ser feita das seguintes maneiras.
• Números inteiros positivos retornam os elementos de acordo com suas posições no vetor.
Para usar este tipo de indexação, devemos escolher a(s) posição(ões) do(s) elemento(s) desejado(s)
e inseríla(s) em um vetor dentro de x[]. Podemos selecionar apenas um elemento, múltiplos ele
mentos ao criar um vetor com suas posições, por meio da função c(), ou até mesmo uma sequência
de elementos, com base em suas posições, por meio do caractere :, como no exemplo abaixo:
## [1] 1.2
• Números inteiros negativos excluem os elementos de acordo com suas posições no vetor.
Incluir o sinal de negativo (-) antes do vetor, como em x[-c()], exclui o(s) elemento(s) em questão.
OBS.: Não é possível misturar números inteiros positivos e negativos na seleção de elementos de
um vetor. Ao fazer isto, é exibida a seguinte mensagem: Error in x[c()] : only 0's may
be mixed with negative subscripts.
Operações lógicas podem ser usadas para selecionar elementos de um vetor. Primeiramente, pode
mos identificar os vetores que queremos selecionar utilizando os operadores TRUE e FALSE, tendo
em vista suas posições no vetor.
Além disso, podemos utilizar expressões lógicas para selecionar elementos de um vetor, de acordo
com a condição desejada.
# Selecionar todos os elementos de `x` cujos valores são superiores a 3
x[x > 3]
A aplicação desta forma de indexação é mais usual em matrizes e data.frames ou para uma nova
designação de objetos a partir do objeto original.
# []: Vetor original
x[]
Esta aplicação pode ser utilizada para gerar dados para teste.
## numeric(0)
• Nomes dos elementos retornam os elementos selecionados (somente se o vetor possuir este
atributo).
Se o vetor possuir o atributo names, podemos selecionar os elementos desejados de acordo com os
nomes designados a eles. Para tanto, devemos incluir os nomes como caracteres, i.e., entre aspas
(' ou ").
## a b c d e
## 3.1 1.2 4.3 5.4 2.5
## d e
## 5.4 2.5
# De maneira semelhante aos índices, podemos repetir os nomes para repetir seus valores
x[c('b', 'b', 'a')]
## b b a
## 1.2 1.2 3.1
OBS.: Como visto, a função letters() representa uma das constantes incluídas no R e contém
as letras do alfabeto em caixa baixa. Outras constantes são LETTERS (letras do alfabeto em caixa
alta), month.abb (abreviação de três letras dos meses em inglês), month.name (nomes dos meses
em inglês) e pi (a razão da circunferência de um círculo por seu diâmetro). Para mais detalhes,
consultar ?letters.
A indexação de matrizes (vetores atômicos multimensionais) possui similaridades com a usada para
vetores atômicos unidimensionais, mas também algumas particularidades.
# Criar uma matriz `y`
y <- matrix(11:22, nrow = 4, ncol = 3)
colnames(y) <- c(LETTERS[1:3])
y
## A B C
## [1,] 11 15 19
## [2,] 12 16 20
## [3,] 13 17 21
## [4,] 14 18 22
## [1] 12
## [1] 20
Ou seja,
matriz[linhas, colunas]
Desta forma, podemos selecionar os elementos de acordo com suas posições na matriz.
## A
## 14
## C
## 19
## [1] 19 20
## A B C
## 11 15 19
## [1] 15 16 17 18
## A B C
## [1,] 11 15 19
## [2,] 12 16 20
OBS.: Esta característica (de selecionar dimensões inteiras pelo operador [) é compartilhada com
as bases de dados (data.frames) e representa uma maneira extremamente útil de se selecionar
elementos (sejam individuais, sejam linhas e colunas inteiras) destes objetos.
Adicionalmente, em matrizes que possuem o atributo names, como a criada anteriormente, podemos
selecionar os elementos destas porções nomeadas. No exemplo, demos nomes às colunas de y.
Desta forma, podemos selecionálas, respeitando a sintaxe matriz[linhas, colunas].
## [1] 11 12 13 14
## B C
## [1,] 15 19
## [2,] 16 20
## [1] 11 12 13 14
class(y[ , 1])
## [1] "integer"
str(y[ , 1])
## int [1:4] 11 12 13 14
## A
## [1,] 11
## [2,] 12
## [3,] 13
## [4,] 14
## int [1:4, 1] 11 12 13 14
## - attr(*, "dimnames")=List of 2
## ..$ : NULL
## ..$ : chr "A"
Como visto, sem especificar drop = FALSE, o objeto retornado de y[ , 1] é um vetor de números
inteiros, sem atributos, isto é, sem dimensões nem nomes. Ao especificar o argumento drop =
FALSE, contudo, o objeto retornado possui sua classe preservada (matrix) e seus atributos, como
os nomes. Esta característica é uma fonte de possíveis erros e uma das justificativas para a utilização
de tibbles no lugar de data.frames. Para mais detalhes, ver Wickham (2015a) e Wickham and
Grolemund (2017).
## [[1]]
## [1] 1
##
## [[2]]
## [1] 2
##
## [[3]]
## [1] 3
A função str() é bastante útil na utilização de listas, por apresentar sua estrutura, no lugar de seu
conteúdo.
# Função `str()`
str(lista)
## List of 3
## $ : num 1
## $ : num 2
## $ : num 3
## List of 3
## $ A: num 1
## $ B: num 2
## $ C: num 3
## [[1]]
## [1] 1
##
## [[2]]
## [1] 2
##
## [[3]]
## [1] 3
## $A
## [1] 1
##
## $B
## [1] 2
##
## $C
## [1] 3
## List of 4
## $ logico : logi [1:2] TRUE FALSE
## $ inteiro : int [1:6] 100 101 102 103 104 105
## $ reais : num [1:5] 0 0.25 0.5 0.75 1
## $ caracteres: chr [1:7] "z" "y" "x" "w" ...
## List of 3
## $ lista_A:List of 4
## ..$ logico : logi [1:2] TRUE FALSE
## ..$ inteiro : int [1:6] 100 101 102 103 104 105
## ..$ reais : num [1:5] 0 0.25 0.5 0.75 1
## ..$ caracteres: chr [1:7] "z" "y" "x" "w" ...
## $ lista_B:List of 1
## ..$ : chr [1:3] "a" "b" "c"
## $ vetor_C: int [1:10] 1 2 3 4 5 6 7 8 9 10
# Operador `[`
lista["logico"]
## $logico
## [1] TRUE FALSE
str(lista["logico"])
## List of 1
## $ logico: logi [1:2] TRUE FALSE
lista2[c(1,3)]
## $lista_A
## $lista_A$logico
## [1] TRUE FALSE
##
## $lista_A$inteiro
## [1] 100 101 102 103 104 105
##
## $lista_A$reais
## [1] 0.00 0.25 0.50 0.75 1.00
##
## $lista_A$caracteres
## [1] "z" "y" "x" "w" "v" "u" "t"
##
##
## $vetor_C
## [1] 1 2 3 4 5 6 7 8 9 10
# Operador `[[`
lista[[1]]
str(lista[[1]])
# Operador `$`
lista$logico
str(lista$logico)
Como visto, podemos selecionar elementos de listas que estão contidas em outras listas.
str(lista2$lista_A$inteiro)
## $inteiro
## [1] 100 101 102 103 104 105
str(lista2[[1]][2])
## List of 1
## $ inteiro: int [1:6] 100 101 102 103 104 105
## $inteiro
## [1] 100 101 102 103 104 105
str(lista2[["lista_A"]]["inteiro"])
## List of 1
## $ inteiro: int [1:6] 100 101 102 103 104 105
## [1] 2
lista2[["vetor_C"]][2]
## [1] 2
## [1] "b"
Dica: Nomear os elementos das listas ajuda bastante, pela praticidade do operador $.
A estrutura de listas pode ser relativamente complexa e a representação de seus elementos e das
formas de indexação não é muito visual. Para facilitar o entendimento, este esquema de repre
sentação, criado por Wickham and Grolemund (2017), ou este, criado por Wickham (2015a), são
extremamente úteis, por serem bastante intuitivos.
• O atibuto names() de uma data frame corresponde aos nomes de suas colunas, que também
podem ser designados por colnames(). Os nomes das linhas é obtido por rownames().
• A quantidade de colunas de uma base de dados é obtida por ncol() ou pelo comando
length(base_de_dados). A quantidade de linhas é obtida por nrow().
## A B
## 1 0.0 10
## 2 0.5 20
str(df)
A instalação padrão do R vem com diversas bases de dados incluídas no programa (builtin da
tasets), que podem ser utilizadas para testar funções e entender melhor o funcionamento geral da
linguagem. Estas bases encontramse no pacote datasets, carregado automaticamente ao iniciar
o R. Para acessar a lista completa de base de dados de exemplos do R, utilizar o comando data()
sem nenhum argumento.
As bases de dados incluídas no pacote datasets já estão automaticamente disponíveis para serem
usadas no R. Para isto, basta apenas digitar seu nome (em uma função, no console, etc).
Acima, visualizamos a estrutura e as cinco primeiras linhas da base de dados iris por meio da
funcão head().
Além disso, outros pacotes, dplyr e ggplot2, por exemplo, vêm com bases de dados que são
usadas nos exemplos contidos em suas documentações.
Como dito, bases de dados possuem características de matrizes e listas. Desta forma, a seleção de
seus elementos compartilham aspectos destes outros tipos de objetos. Podemos utilizar os opera
dores [, [[ e $.
Em contrapartida, [[ e $ retornam o elemento individual da base de dados, sem manter seus atri
butos, ou seja, sem preservar a estrutura inicial do objeto.
## num [1:150] 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
Quando usamos os dois indexadores na seleção de elementos de bases de dados (linhas e colunas),
as bases de dados se comportam como matrizes na operação de seleção. Assim, utilizase a sintaxe
conhecida:
base_de_dados[linhas, colunas]
de modo que podemos selecionar elementos individuais de uma linha, coluna ou linhas inteiras e
colunas.
## [1] 10 20
Há uma importante diferença ao selecionar elementos de uma base de dados pela sintaxe de listas
(base_de_dados[indexador]) e de matrizes (base_de_dados[linhas, colunas]), utilizando
o operador [. Analogamente à indexação de matrizes, ao selecionarmos apenas uma coluna pela
sintaxe base_de_dados[linhas, colunas], a estrutura do objeto resultante é simplificada (i.e.,
o objeto resultante passa a ser um vetor atômico), enquanto enquanto a indexação de listas preserva
a estrutura do objeto original (o objeto resultante é uma base de dados). Para preservar a estrutura
original do objeto pela sintaxe base_de_dados[linhas, colunas], devemos incluir o argumento
drop = FALSE.
## num [1:2] 10 20
A partir dos conceitos expostos sobre base de dados (nomes das colunas, seleção de suas colunas,
etc) podemos fazer algumas operações bastante úteis com estes objetos a partir das funções base do
R.13
Para renomear as colunas de uma base de dados, podemos utilizar as funções colnames() ou
names().
13
Existem soluções mais elegantes e eficientes para realizar estas e operações semelhantes com base de dados, porém
são necessárias a utilização de outros pacotes (como data.table e o próprio tidyverse), além do conhecimento
de outros tópicos que fogem do conhecimento deste documento (criação de funções, pipes, etc). Optouse por focar
nas formas essenciais de execturar estas tarefas.
Podemos renomear uma coluna de acordo com seu nome, sem depender, portanto, de
sua posição na base de dados, por meio do seguinte código: names(df)[names(df) ==
'nome_coluna_antigo'] <- 'nome_coluna_novo'
Podemos usar o operador [ para reordenar as colunas de uma base de dados a partir de seus nomes
ou posições.
Podemos excluir colunas de uma base de dados por nome ou posição, de várias maneiras.
Analogamente, podemos utilizar os operadores para adicionar colunas a uma base de dados.
2.5.0.4 Tibble
O objeto tibble é uma reimaginação do data frame, criado para lidar com alguns problemas usuais
obtidos no uso destes objetos. As referências utilizadas neste livro recomendam o uso deste objetos,
então vale a pena descobrir algumas de suas especificidades, nesta subseção do livro de Wickham
ou no Capítulo sobre tibbles do livro seminal de Wickham e Grolemund.