Introdução

R é um ambiente de programação voltado para manipulação, análise de dados e apresentação gráfica. R é um projeto em constante desenvolvimento resultado de esforços colaborativos com contribuições de todo o mundo. Disponibiliza uma ampla variedade de métodos estatísticos e gráficos, sendo ainda facilmente extensível através de pacotes ou funções desenvolvidas pelos próprios usuários. O R possue uma estrutura de código aberto (open source) com linguagem de programação multiparadigma, sendo que tarefas computacionais intensivas podem ser realizadas por meio de integração de códigos em C, C++, Java, Python e Fortran. O R tem a sua própria documentação em formato semelhante a LaTeX, que é usada como documentação das funções.

Este texto trata dos principais aspectos da linguagem R e tentará ensinar R em 10 minutos. Obviamente que não é possível aprender uma linguagem de programação em apenas alguns minutos, para realmente aprender R é preciso programar e exercitar por um tempo. O texto mostrará alguns conceitos básicos para começar, como sintaxe, operações, tipos de dados, estruturas, declarações de controle de fluxo e funções. A ideia é que o leitor seja capaz de reproduzir os comandos aqui contidos e exercitar os conceitos apresentados. Algumas conceitos serão introduzidas diretamente no código e apenas brevemente comentados. Ao final também é apresentado um guia de ajuda rápida mostrando as principais palavras da sintaxe, operadores e funções da linguagem R apresentados aqui.

Propriedades

R possui fortes recursos de programação orientada por objetos, sendo que tudo é considerado objeto. A tipagem é dinâmica, não exigingo declarações prévias do tipos de dados do objeto. É uma linguágem sensível à caixa das letras (case-sensitive), ou seja, var e VAR são consideradas duas variáveis diferentes.

Obtendo ajuda

A ajuda está sempre disponível diretamente no interface. O funcionamento da função pode ser obtido usando as funções help (atalho ?). Argumentos das funções podem ser obtidos com a função args, classes dos objetos pela função class e estrutura dos objetos pela função str. Ainda é possivel pesquisar por assunto, usando a função help.search (atalho ??).

Sintaxe

O R não possui caracteres de terminação de instrução obrigatórios e os blocos são especificados por chaves ({}). Os comentários começam com sustenido (#) e não há sintaxe para comentários em multiplas linhas. Valores são atribuídos (na verdade, objetos são vinculados a nomes) com os sinais de “<-”, “=” ou “->” (mais usado é o “<-” enquanto que “=” é obrigátorio quando usado para especificar argumentos das funções). Os indentificadores das variáveis (nomes dos objetos) podem ser uma combinação de letras, dígitos, ponto (.) ou underline (_), devendo começar com letras ou digítos. Quando começam com um ponto, não poderão ser seguido por um dígito. O teste de igualdade é feito usando dois sinais de igual (“==”). Não há operadores de incremendo direto. As vírgulas (,) separam argumentos em uma função, sendo que é possível usar várias variáveis em uma linha. Outras informações sobre sintaxe são encontradas em ?Syntax.

Tipos de dados

Os tipos de dados podem ser numéricos (numeric), caracter (character) ou lógicos (logical). Os dados do tipo numeric são número inteiros, reais e complexos. Podem serem escritos também com notação científica, utilizando o E (ou e), se numéricas são seguidos pela letra L são considerados inteiro e se seguidos pela letra i são consideradas complexos. O tipo character armazena caracteres ou texto e são escritos obrigatoriamente entre aspas duplas ("") ou simples (’’). As dados boleanos (verdadeiros ou falsos) são definidos como TRUE e FALSE (abreviação T e F respectivamente). A função typeof mostra o tipo de modo de armazenamento de qualquer objeto. A conversão entre tipos é livre feita pelas funções de prefixo as. (por exemplo as.numeric()) e a checagem lógica feita pelas funções de prefixo is. (por exemplo is.numeric()).

Operações aritméticas e lógicas

As operações aritméticas básicas e testes lógicos são disponíveis. Mais informações sobre operações são encontradas em ?Arithmetic, ?Comparison e ?Logic .

Operadores & e | fazem a operação elementar produzindo resultados de comprimento do operador mais longo. Já && e || examinam apenas o primeiro elemento dos operadores e como resultado apenas um único valor lógico é retornado. Zero é sempre considerado FALSE e números diferentes de zero são considerados TRUE.

Tipos de estruturas

As estruturas básicas de dados disponíveis são vetores (vector), fatores (factor), data.frames (data.frame), matrizes (matrix) e listas (list). Os vetores e fatores são conjuntos de dados unidimensionais do mesmo tipo. Os vetores podem conter dados lógicos (logical), inteiros (integer), reais (double), caracteres (character) ou complexos (complex), são geralmente concatenados pela função (c) e sempre separados por vírgulas (,). Os fatores são estruturas de dados usada para dados (numeric ou character) com um número finito (predefinido) de categorias, podendo estas serem ordenadas ou não. Fatores são definidos pelas função factor e ordered. Os data.frames são conjuntos bidimensionais de vetores de mesmo comprimento sendo que cada vetor pode ser de tipos diferentes. Os data.frames são criados pela função (data.frame) onde os vetores são agrupados nas coluna e o conteúdo dos vetores formam as linhas. As matrizes também são conjuntos bidimensionais de dados do mesmo tipo, podem ser criadas com a função matrix ou com a combinação de vetores com as função cbind e rbind (concatena os vetores por coluna ou por linhas respectivamente). A listas são conjuntos de dados de qualquer tipo (incluindo listas de listas), são criadas com a função list. Vetores, fatores e listas podem conter nomes (acessados ou atribuidos pela função names) e possuem como atributo o comprimento (obetidos pela função length). Os data.frames e matrizes podem conter nomes para linhas e colunas (acessados ou atribuidos pelas funções rownames e colnames, respectivamente) e contêm como atributos os números de colunas e linhas (obetidos pelas funções ncol e nrow, respectivamente). O índice do primeiro item é sempre o um (1). Os intervalos das estruturas podem ser acessadas usando dois pontos (:). Os índice com números negativos retornam todos menos os especificados. A indexação também ser realizada com vetores lógicos e com nomes nos casos de estruturas nomeadas. A função str exibir resumidamente a estrutura interna dos objeto no R. A conversão entre estruturas é livre feita pelas funções de prefixo as. (por exemplo as.matrix()) e a checagem lógica feita pelas funções de prefixo is. (por exemplo is.data.frame()).

# Estruturas
vetor <- c("a", "b", "c", "d") 
vetor
[1] "a" "b" "c" "d"
class(vetor)
[1] "character"
names(vetor)
NULL
names(vetor) <- c("letra1", "letra2", "letra3", "letra4")
vetor
letra1 letra2 letra3 letra4 
   "a"    "b"    "c"    "d" 
fator <- factor(c("a", "b", "c"))
fator
[1] a b c
Levels: a b c
levels(fator)
[1] "a" "b" "c"
fator.ordenado <- ordered(c("a", "b", "c"))
fator.ordenado
[1] a b c
Levels: a < b < c
dataframe <- data.frame(vetor.de.caracteres = vetor, vetor.numerico = 1:4)
dataframe
       vetor.de.caracteres vetor.numerico
letra1                   a              1
letra2                   b              2
letra3                   c              3
letra4                   d              4
str(dataframe) 
'data.frame':   4 obs. of  2 variables:
 $ vetor.de.caracteres: chr  "a" "b" "c" "d"
 $ vetor.numerico     : int  1 2 3 4
ncol(dataframe)
[1] 2
nrow(dataframe)
[1] 4
matriz <- matrix(data = 1:20, nrow = 5, ncol = 4) # cbind e rbind também podem ser usadas
matriz # Por padrão os dados são organizados por colunas
     [,1] [,2] [,3] [,4]
[1,]    1    6   11   16
[2,]    2    7   12   17
[3,]    3    8   13   18
[4,]    4    9   14   19
[5,]    5   10   15   20
str(matriz) # Apenas uma tipo de dado é permitido
 int [1:5, 1:4] 1 2 3 4 5 6 7 8 9 10 ...
lista <- list(1, dataframe, matriz, list("outra", "lista"))
lista
[[1]]
[1] 1

[[2]]
       vetor.de.caracteres vetor.numerico
letra1                   a              1
letra2                   b              2
letra3                   c              3
letra4                   d              4

[[3]]
     [,1] [,2] [,3] [,4]
[1,]    1    6   11   16
[2,]    2    7   12   17
[3,]    3    8   13   18
[4,]    4    9   14   19
[5,]    5   10   15   20

[[4]]
[[4]][[1]]
[1] "outra"

[[4]][[2]]
[1] "lista"
names(lista)
NULL
names(lista) <- c("l1", "l2", "l3", "l4")
lista
$l1
[1] 1

$l2
       vetor.de.caracteres vetor.numerico
letra1                   a              1
letra2                   b              2
letra3                   c              3
letra4                   d              4

$l3
     [,1] [,2] [,3] [,4]
[1,]    1    6   11   16
[2,]    2    7   12   17
[3,]    3    8   13   18
[4,]    4    9   14   19
[5,]    5   10   15   20

$l4
$l4[[1]]
[1] "outra"

$l4[[2]]
[1] "lista"
length(lista)
[1] 4

# Indexação das estruturas
vetor[1] # Primeiro elemento
letra1 
   "a" 
vetor[c(FALSE, FALSE, TRUE, FALSE)] # Indexação com valores lógicos
letra3 
   "c" 
vetor[1:3] # Primeiro a terceiro elementos
letra1 letra2 letra3 
   "a"    "b"    "c" 
vetor[] # Todos
letra1 letra2 letra3 letra4 
   "a"    "b"    "c"    "d" 
vetor[-1] # Todos, exceto o primeito elemento
letra2 letra3 letra4 
   "b"    "c"    "d" 
vetor[c(1, 4)] # vetor[1, 4] não funciona
letra1 letra4 
   "a"    "d" 
vetor["letra4"] # Pelo nome
letra4 
   "d" 
vetor[1] <- "z" # muda o valor do item 1
vetor
letra1 letra2 letra3 letra4 
   "z"    "b"    "c"    "d" 
vetor <- NULL # Vetor deletado
vetor
NULL

fator
[1] a b c
Levels: a b c
fator[1] <- "c" # mudar de fator
fator # nívels permanecem
[1] c b c
Levels: a b c
fator[1] <- "z" # fator inválido
Warning in `[<-.factor`(`*tmp*`, 1, value = "z"): invalid factor level, NA generated
fator # NA é gerado
[1] <NA> b    c   
Levels: a b c

dataframe[1] # Mostra primeiro vetor (coluna)
       vetor.de.caracteres
letra1                   a
letra2                   b
letra3                   c
letra4                   d
dataframe$vetor.de.caracteres # Indexação pelo nome
[1] "a" "b" "c" "d"
dataframe[1, ] # Linha
       vetor.de.caracteres vetor.numerico
letra1                   a              1
dataframe[, 2] # Coluna. Por padrão a estrutura é convenvertida em vetor...
[1] 1 2 3 4
dataframe[, 2, drop = FALSE] # ... Mantém a estrutura de data.frame
       vetor.numerico
letra1              1
letra2              2
letra3              3
letra4              4
dataframe[,] # Tudo
       vetor.de.caracteres vetor.numerico
letra1                   a              1
letra2                   b              2
letra3                   c              3
letra4                   d              4
dataframe[, 2] <- NULL # Apenas colunas podem ser deletadas
dataframe$novo.vetor <- c("a", "b", "c", "d") # Adicionar vetor...
str(dataframe) # ... nesse caso a classe permanece
'data.frame':   4 obs. of  2 variables:
 $ vetor.de.caracteres: chr  "a" "b" "c" "d"
 $ novo.vetor         : chr  "a" "b" "c" "d"

matriz[1, ]
[1]  1  6 11 16
matriz[, 2]
[1]  6  7  8  9 10
matriz[, 2, drop = FALSE] # Matriz 1x5, não um vetor
     [,1]
[1,]    6
[2,]    7
[3,]    8
[4,]    9
[5,]   10
matriz[1, 4] # Um elemento da matriz
[1] 16
matriz[1, 4] <- 0 # Nada pode ser deletado, apenas alterado de valor (incluindo NA)

str(lista)
List of 4
 $ l1: num 1
 $ l2:'data.frame': 4 obs. of  2 variables:
  ..$ vetor.de.caracteres: chr [1:4] "a" "b" "c" "d"
  ..$ vetor.numerico     : int [1:4] 1 2 3 4
 $ l3: int [1:5, 1:4] 1 2 3 4 5 6 7 8 9 10 ...
 $ l4:List of 2
  ..$ : chr "outra"
  ..$ : chr "lista"
lista[2] # Acessar sublista
$l2
       vetor.de.caracteres vetor.numerico
letra1                   a              1
letra2                   b              2
letra3                   c              3
letra4                   d              4
lista[[2]] # Acessar conteúdo da lista
       vetor.de.caracteres vetor.numerico
letra1                   a              1
letra2                   b              2
letra3                   c              3
letra4                   d              4
lista[1:3] # Acessar várias sublistas. lista[[1:3]] não funciona
$l1
[1] 1

$l2
       vetor.de.caracteres vetor.numerico
letra1                   a              1
letra2                   b              2
letra3                   c              3
letra4                   d              4

$l3
     [,1] [,2] [,3] [,4]
[1,]    1    6   11   16
[2,]    2    7   12   17
[3,]    3    8   13   18
[4,]    4    9   14   19
[5,]    5   10   15   20
lista[["l3"]][1,3] # Usando nomes e elemento da matriz
[1] 11
lista[["l3"]] <- NULL # Deletar item da lista. Mesmo que lista["l3"], lista[3], lista[[3]]
lista$novoitem <- 1:3 # Adicionar item a lista
lista
$l1
[1] 1

$l2
       vetor.de.caracteres vetor.numerico
letra1                   a              1
letra2                   b              2
letra3                   c              3
letra4                   d              4

$l4
$l4[[1]]
[1] "outra"

$l4[[2]]
[1] "lista"


$novoitem
[1] 1 2 3

Funções

As funções são declaradas com a palavra function. Outros argumentos, obrigatórios ou opcionais, são definidos na declaração da função entre parênteses (()), podendo estes conter valores predefinidos (default). Os argumentos das funções seguem a ordem especificada na declaração da função, podendo ou não ser nomeados ao atributi o valor. Se argumentos são nomeados não precisam seguir a ordem predefinida. A função return especifica o que é retornado. A função só pode retornar um objeto, mas pode ser uma lista com vários valores. Uma função pode ser recursiva (recursive), chama a si mesma, podendo ser usada para resolver problemas dividindo-os em subproblemas menores e mais simples. É possível definir operações com notação infixa (infix operator). Para definição de operações infixas a definição das funções devem iniciar e terminar % e devem ser usadas aspas simples (’’) para indicar notação de símbolo especial. Mais informações sobre funções são encontradas em ?“function”.

Ambiente e escopo das variávels

O R usa o conceito de ambiente (environment) para armazenar as variáveis (objetos e funções por exemplo). O principal ambiente (global) é denominado R_GlobalEnv (.GlobalEnv nos códigos) e definido automaticamente ao abrir o programa. Podem existir múltiplos ambientes simultaneamente, sendo que na definição de novas funções um novo ambiente é criado para armazenar as variáveis locais. Existe uma distinção entre variáveis globais e locais, que são armazenadas em diferentes ambientes. Variáveis globais são aquelas variáveis que existem durante a execução de um programa, podem ser alteradas e acessadas por qualquer parte do programa. Variáveis locais são aquelas que existem apenas dentro de uma certa parte de um programa, são criadas e destruídas quando a função termina. No entanto, variáveis globais e locais dependem da perspectiva de uma função, já que os ambientes podem estar alinhadas dentro de outros ambientes. A função ls lista os objetos do ambiente atual e a função rm remove os objetos. As variáveis globais podem ser lidas mas não podem ser atribuídas com a atribuição padrão (<-). A atribuição padrão serve apenas para atribuir variáveis locais. Para fazer atribuições a variáveis globais, o operador de super atribuição (<<-) é usado. Ao usar este operador dentro de uma função, ele procura pela variável no ambiente do nível superior, se não for encontrado, continua procurando o próximo nível até atingir o ambiente global. Se a variável ainda não for encontrada, ela será criada e atribuída no nível global.

Classes

R possui um mecanismo de classes e métodos que aplicam as funções de acordo com as classes herdadas dos objetos, no estilo de programação orientada por objetos. Existem três sistemas de classes, S3, S4 e Reference Class. A classe S3 é a mais simples, sem qualquer definição formal. Os objetos dessa classe pode ser criado simplesmente adicionando um atributo de classe usando a função class. Uma vez atribuidas os objetos passam a herdar a classe (checados pela função inherits), sendo que os objetos podem herdar mais de uma classe. Na classe S3 os métodos pertencem à funções genéricas junto com outras funções genéricas predefinidas (por exemplo print, summary e plot) que aplicam os métodos de acordo com as classes herdadas dos objetos. Quando uma função genérica é aplicada a um objeto de uma classe (por exemplo “minhaclasse”), o sistema procura por uma função compatível com a classe (por exemplo “funcao.minhaclasse”), se a encontrar aplica o método ao objeto. Se tal função não for encontrada a classe implícita ou método padrão serão tentados. É possível derivar novas classes das classes existentes e adicionar novos métodos ou criar funções genéricas próprias.

Exceções

O R oferece funções para lidar com condições incomuns, incluindo erros e avisos. As funções message e warning são usadas para mostrar mensagens de diagnóstico e advertência respectivamente. Erros que interompem a execução do código podem ser atribuidos pela função stop. A função try pode ser usada como uma funçõe envelope (wrapper function) para executar uma função que pode falhar, permitindo a recuperação de erros. A função retorna o resultado normal da função caso executada sem erro, mas um objeto da classe “try-error” contendo a mensagem de erro e a condição de erro é retornado caso houver alguma falha. Outras funções sobre condições incomuns são encontradas em ?conditions.

Importando

Bibliotecas externas (chamados de pacotes ou packages) podem ser instaladas (função install.packages) e carregadas com a função require ou library. É possível usar funções individuais usando :: para chamar funções dos namespaces dos pacotes instalados.

Importando e exportando arquivos

O R possui uma grande variedade de pacotes embutidos que permitem importar e exportar arquivos nos mais diversos formatos. Funções como read.table, read.csv, write.table e write.csv do pacote utils permitem importar (prefixo read.) e exportar (prefixo write.) tabelas de dados. As funções do pacote grDevices como pdf, png, tiff, jpeg permitem abrir dispositivos para exportar gráficos (a função dev.off precisa ser usada para fechar os dispositivos gráficos). Existem também funções para criar, abrir e fechar conexões com arquivos e URLs, lista completa disponível em ?connections. O R sempre fica associado a uma diretório do computador, esse será o diretório de trabalho (working directory). Os arquivos que estão neste diretório podem ser carregados apenas pelo nome e qualquer arquivo exportado será salvo neste diretório caso não especificado o contrário. Os sistemas de caminhos (path), absolutos ou relativos, podem ser usados especificar a localização dos arquivos (por exemplo ./subdiretorio e ..) e a funções file.choose permitem escolher arquivos interativamente. As funções save.image e load permitem respectivamente salvar e carregar área de trabalho (workspace) e a função source importar arquivos de códigos em R.

Geração de números aletórios e amostragem

O R possui um conjunto grande de funções ligadas às distribuições de probabilidade, simulação de distribuições e reamostragem de dados. Amostras aleatórias e permutações podem ser realizadas pela função sample. As funções de densidade/massa, distribuição cumulativa e quantílica e geração de variáveis aleatórias pode realizadas para as principais distribuições de probabilidade. A lista completa disponível em ?Distributions.

Guia de ajuda rápida

# - Adicionar comentário
? - Obter ajuda de função
?? - Relizar buscar
<- ou = - Atribuir objeto (direita para esquerda)
-> - Atribuir objeto (esquerda para direita)
<<- - Super atribuir objeto (direita para esquerda)
->> - Super atribuir objeto (esquerda para direita)
+ - Somar
- - Subtrair
* - Multiplicar
/ - Dividir
^ - Potêncializar (direita para esquerda)
%/% - Parte inteira da divisão
%% - Resto da divisão
%*% - Multiplicar matrizes
%o% - Produto diádico
%x% - Produto de Kronecker
%in% - Operador de correspondência
< - Comparar, menor
> - Comparar, maior
<= - Comparar, menor ou igual
>= - Comparar, maior ou igual
== - Comparar, exatamente igual
!= - Comparar, diferente 
! - Lógico, NÃO. Inverter resultado de teste lógico
& - Lógico, critério aditivo E. Operação elementar
| - Lógico, critério aditivo OU. Operação elementar
&& - Lógico, E
|| - Lógico, OU
~ - Fórmula estatística
FALSE ou F - Argumento lógico falso
TRUE ou T - Argumento lógico verdadeiro
NA - Indeterminado (Not Avaiable)
NaN - Indeterminado (Not a Number)
Inf - Infinito
NULL - Objeto nulo
c() - Concatenar valores em vetor
factor() - Criar fator
ordered() - Criar fator ordenado
data.frame() - Criar tabela de dados (data.frames)
matrix() - Criar matriz
list() - Criar lista
rbind() - Combinar vetores por linhas
cbind() - Combinar vetores por colunas
paste() - Concatenar caracteres em sequências regulares
class() - Conferir/Atribuir classe do objeto
str() - Conferir estrutura do objeto
: - Gerar sequência numérica contínua
$ - Indexar vetores/listas pelo nome das variáveis/listas
@ - Indexar na classe S4 
[] - Indexar vetores/listas
[ , , drop = FALSE] - Indexar data.frames/matrizes. Primeiro valor linha, segundo coluna
[[]] - Indexar listas
:: ou ::: - Acessar variável em um namespace
names() - Conferir/Atribuir nomes a vetores/listas
colnames() - Conferir/Atribuir nomes as linhas de data.frames/matrizes
rownames() - Conferir/Atribuir nomes as colunas de data.frames/matrizes
length() - Conferir comprimento de vetores/listas
nrow() e ncol() - Conferir dimensões de data.frames/matrizes
t() - Transpor data.frames/matrizes
seq() - Obter sequência regular
rep() - Repetir valores
ifelse() - Aplicar teste condicional
read.csv() ou read.table() - Importar tabelas
write.csv() ou write.table() - Exportar tabelas
ls() - Listar objetos da área de trabalho
rm() - Remover objetos da área de trabalho
save.image() - Salvar área de trabalho
load() - Carregar área de trabalho
if(condição) expressão - Controle de fluxo, SE
if(condição) expressão.da.condição  else  expressão.alternativa - Controle de fluxo, SE/SENÃO
for(variável in sequência) expressão - Controle de fluxo, LAÇO/LOOP.
while(condição) expressão - Controle de fluxo, ENQUANTO
repeat expressão - Controle de fluxo, REPETIR
break - Controle de fluxo, PARAR
next - Controle de fluxo, PRÓXIMO
function(lista.de.argumentos) expressão - Funções. Criar função
return(valor) - Funções. Resultado/returno da função
message() - Funções. Criar mensagens de diagnóstico
warning() - Funções. Criar mensagens de advertência
stop() - Funções. Criar mensagens de erro
try() - Funções. Tentar função envelope

Conclusão

O objetivo deste texto foi introduzir alguns conceitos básicos da linguagem R. Os principais aspectos da sintaxe, operadores, tipos de dados, estruturas dos objetos, controle de fluxo e desenvolvimento de funções foram mostradas e exemplificadas. Espero que este texto tenha sido útil e, por favor, avise-me se tiver dúvidas ou sugestões sobre este texto.

Mais informações

Outros textos e tutoriais sobre R podem ser encontrados em https://vanderleidebastiani.github.io/tutoriais.

Referências