Instalação e Uso

O R está disponível gratuitamente na internet. Para facilitar seu uso é fortemente recomendado que se instale também o RStudio. O RStudio é uma interface gráfica para o R que traz diversas funcionalidades úteis. Ele também é integrado com o Markdown e o Notebook que permitem compartilhar códigos de R. Este html, por exemplo, foi renderizado a partir de um arquivo de Markdown escrito no RStudio. Também é possível escrever código diretamente em editores de texto (ex: Notepad++, Sublime Text), mas isto não é recomendado para usários iniciantes. Também há outras interfaces gráficas que permitem o uso do R “apontando e clicando”; talvez o mais popular deles seja o RCommander. A longo prazo, contudo, este tipo de interface acaba sendo restritiva; vale a pena investir tempo e aprender a usar o R programando.

Para instalar o R:

Para instalar o RStudio:

Recursos Online

Como o R é opensource há uma vicejante comunidade online cultivada em seu entorno. Talvez a habilidade mais importante para aprender a usar o R é saber utilizar o google. Há milhares de usuários usando o R no mundo inteiro e, via de regra, já existe uma solução para qualquer problema que você pode encontrar. Uma pesquisa no google costuma ser suficiente para resolver qualquer problema no R. Também é possível encontrar vários tutoriais e livros (gratuitos) de R e econometria.

Muitos destes recursos online estão categorizados genericamente na rubrica de data science (ciência de dados). Outro termo bastante na moda é machine learning. Uma pequena distinção que vale a pena ser feita é entre econometria, ciência de dados e machine learning. Ciência de dados é um termo bastante amplo para designar métodos científicos, processos e algoritmos que visam extrair conhecimento e insights de bases de dados. Neste sentido, machine learning faz parte da ciência de dados. Na prática, cursos de ciências de dados ou livros de ciências de dados aplicados ao R costumam enfatizar habilidades como mineração (webscrapping), manipulação e visualização de dados, buscando encontrar correlações e padrões (em geral de maneira automatizada) em bases de dados grandes. Algumas destas habilidades são bastante úteis para econometristas, ainda que um cientista de dados lide com problemas de programação e engenharia de software que estão fora do domínio da econometria.

Há diversos métodos compartilhados e modelos híbridos de machine learning e econometria. O modelo de regressão linear, por exemplo, é comumente utilizado tanto para explicar o comportamento entre as variáveis quanto para prever o seu comportamento futuro. Ou seja, na prática os métodos e princípios são complementares. O economista Hal Varian (o mesmo do livro-texto de micro) publicou na American Economic Review uma revisão de métodos de machine learning e econometria, enfatizando vantagens e desvantagens de cada um e mostrando como eles podem se complementar.

Na prática, cursos online de “machine learning usando R” ou “ciência de dados no R” costumam incluir vários exemplos de economia. Livros de séries de tempo também costumam incluir muitas aplicações usando dados econômicos e apresentam as muitas das mesmas técnicas que aprendemos em econometria.

Introduções ao R

  • Introdução ao R (FEA-RP). Materiais do curso de programação em R da FEA de Ribeirão Preto.
  • Swirl. O pacote swirl é composto de uma série de aulas sobre R que são apresentadas dentro do prórprio R. Use install.packages('swirl') para instalar o pacote e depois library(swirl) para carregá-lo no R. Finalmente, é só executar swirl() e seguir os passos. Para mais detalhes veja o site. Introduction to R. Introdução ao R disponível no site do Datacamp. Os cursos mais avançados são pagos.
  • Introduction to R for Data Science. Curso gratuito no edX focado em manipulação e visualização de dados.
  • Introduction to R. Curso gratuito do udemy. Bastante introdutório.
  • Cookbook for R, Winston Chang. Site que acompanha o livro introdutório de R, Cookbook for R (disponível gratuitamente). Contém vários exemplos.

Econometria e R

  • Minicurso de Econometria no R, C.D. Shikida e Rodrigo N. Fernandez (em português)
  • Time Series Analysis and Its Applications With R Examples, Robert Schumway e David Stoffer. Livro de séries de tempo com aplicações no R. Site que acompanha o livro. Os autores do livro são os mesmos do pacote astsa. Livro bastante completo que inclui também tópicos pouco vistos em disciplinas de econometria como análise espectral e modelos de espaço estado.
  • Forecasting: Principles and Practice, Rob J Hyndman e George Athanasopoulos. Livro introdutório sobre métodos de previsão de séries temporais com aplicações práticas no R. Os autores do livro são os mesmos do pacote forecast para o R. Livro mais focado em previsões e muitas vezes inclui modelos ateóricos (i.e., que não explicam a relação entre os dados).
  • Applied Econometrics with R, Christian Kleiber e Achim Zeileis. Livro intermediário de econometria aplicada no R. O livro supõe que o leitor já tenha adquirido conhecimentos de econometria. Os autores do livro são os mesmos do pacote AER que inclui diversas bases de dados e scripts de tutoriais.

Recursos gerais

  • Stackoverflow. Site de perguntas e respostas sobre R. Contém a resposta para praticamente qualquer problema envolvendo R.
  • R Bloggers. Blog colaborativo sobre R. Contém desde tópicos introdutórios até outros bastante avançados.

Introdução

O R é uma linguagem de programação que, grosso modo, funciona como uma linguagem orientada a objetos. Isto é, criamos variáveis e aplicamos funções sobre estas variáveis. Elas podem ser variáveis de vários tipos. As principais são:

  • Numéricas
  • Texto
  • Factor (categorias)
  • Tabelas com dados
  • Séries de tempo

Pense no R como um repositório de pacotes. Instalamos pacotes que são como uma pequena biblioteca de funções, agrupadas por assuntos similares. O pacote xts (eXtensible Time Series) traz uma série de funções para manipular e agregar dados em formato de série temporal. Já o pacote ggplot2 contém várias funções para visualização de dados em gráficos. O R já vem com uma série de funções “pré-instaladas”. Vamos aprender algumas das mais úteis.

Criando objetos

A sintaxe para criar objetos segue a lógica: “[objeto] <- [valor/atributo]”. Então, x <- 3 associa o valor numérico 3 para a letra x. Como mencionado acima, há diversos tipos de objetos que o R consegue interpretar.

# Números
a <- 3
b <- 5
# Texto
c <- "Fernando Pessoa"
# Tabelas
d <- LifeCycleSavings
# Valores lógicos
e <- TRUE

Para verificar a classe dos objetos criados acima usamos a função class(). Dentro do parêntese devemos indicar o objeto ao qual a função está sendo aplicada.

# Para verificar a classe de um objeto
class(a)
## [1] "numeric"
class(c)
## [1] "character"
class(d)
## [1] "data.frame"
class(e)
## [1] "logical"

Também é possível declarar variávei usando a = 3 contudo esta sintaxe pode gerar ambiguidades em contextos específicos. Por isso, recomenda-se que se use sempre a <- 3. Para testes lógicos usamos a sintaxe:

# Testes lógicos
a == b
## [1] FALSE
a != b
## [1] TRUE
class(a) == class(b)
## [1] TRUE

Usando funções

O R inclui diversas funções. A lógica da sintaxe costuma ser “função([objeto 1], [objeto 2], [objeto 3], …)”. Isto fica mais claro com um exemplo. Tome a função rnorm() que sorteia um valor a partir de uma distribuição normal. Os argumentos da função são os seguintes: rnorm(n, mean = 0, sd = 1), onde ‘n’ é o numéro de observações e ‘mean’ e ‘sd’ são a média e o desvio-padrão (sd é abreviação de standard deviation) da normal.

# Exemplo
rnorm(n = 1, mean = 10, sd = 1)
## [1] 10.80941

Alguns pontos à respeito da sintaxe que devem ser levantadas:

  1. O R não leva em consideração espaços, quebras de linha, etc.

O código abaixo exemplifica isto. Contudo, ainda que haja total liberdade para inserir espaços e novas linhas recomenda-se que o código seja escrito de maneira a facilitar sua leitura e interpretação. Dicas de como manter um código limpo e organizado serão oferecidas no final deste tutorial.

rnorm(n = 1,
      mean = 10,
      
                  sd = 1)
## [1] 10.4947
  1. Funções vêm com argumentos e ordens de argumentos padrão.

Note que rnorm(n, mean = 0, sd = 1) implica que ‘mean’ está pré-definido para 0 e ‘sd’, para 1. Isto é, o código rnorm(n = 10) deve retornar 10 observações seguindo uma normal padrão (média zero e variância unitária). Contudo, podemos ir um passo além e omitir o ‘n’. O código rnorm(10) também retorna 10 observações seguindo uma normal padrão. Da mesma forma como omitimos o ‘n’, podemos omitir o ‘mean’ e o ‘sd’ desde que os nossos argumentos respeitem a ordem da função. O código rnorm(10, 5, 2), por exemplo, retorna 10 observações seguindo uma distribuição normal com média 5 e desvio padrão igual a 2. Por fim, também podemos declarar os argumentos fora de ordem: rnorm(mean = 5, sd = 2, n = 10).

Por uma questão de clareza os argumentos neste tutorial serão declarados explicitamente e seguindo a ordem padrão da função.

# Omitindo 'mean' e 'sd'
rnorm(n = 10)
##  [1] -0.5506558 -0.5542272  0.9066178  0.2222919  1.7951715  0.2850000
##  [7]  1.4454305 -0.4345442 -1.0220552 -0.3683243
# Omitindo 'n', 'mean' e 'sd'
rnorm(10)
##  [1] -0.5301983  1.8532585  1.0507243 -1.0966317  1.0252845  1.4756183
##  [7] -1.2086962 -0.3931085 -1.5666683 -1.6518894
# Declarando os argumentos implicitamente
rnorm(10, 5, 2)
##  [1] 1.269060 1.940066 6.862521 4.191450 4.616438 3.478322 2.632197
##  [8] 2.506124 2.084465 5.786595
# Declarando explicitamente e fora de ordem
rnorm(mean = 5, sd = 2, n = 10)
##  [1] 5.040492 4.445633 3.314273 4.766228 5.635235 5.263139 6.780863
##  [8] 3.092519 4.624598 3.532494
# Neste tutorial vamos sempre (tentar) escrever
rnorm(n = 10, mean = 0, sd = 1)
##  [1]  0.58089691 -0.06686082 -0.73202626  0.63861070 -0.71752645
##  [6]  0.70570256 -0.49994522  1.38409834 -0.78269783 -0.52613851

Instalando pacotes

Para instalar novos pacotes usamos a função install.packages("nome_do_pacote"). Enquanto o RStudio automaticamente seleciona um servidor para baixar o pacote, no R é preciso escolher um manualmente. Recomenda-se que se escolha o servidor que for mais próximo geograficamente. Depois de instalados, é preciso sempre usar a função library(nome_do_pacote) para carregá-los. Alguns pacotes exigem a instalação conjunta de outros - em geral, não é preciso se preocupar com isto pois eles são todos instalados ao mesmo tempo. Um pacote muito útil e popular é o tidyverse que, na verdade, é uma família de pacotes para ciência de dados. Para instalar este pacote use install.packages("tidyverse"). Depois, para carregá-lo use library(tidyverse). Alguns pacotes úteis:

Manipulação de dados
dplyr Manipulação de dados. Mais eficiente do que as funções base do R.
data.table Manipulação de dados. Um pouco mais eficiente do que o dplyr quando tratando de bases de dados grandes.
readxl Importa dados do excel.
haven Importa dados do Stata (.dta).
Visualização de dados
ggplot2 Visualização de dados.
plotly Visualização de dados. Permite a criação de gráficos interativos. Número limitado de gráficos gratuitos.
Séries de tempo
xts / zoo Facilita a manipulação de séries de tempo.
lubridate Facilita a manipulação de séries de tempo. Especialmente útil para manipular datas.
forecast Modelos de previsão para séries de tempo. Integra séries de tempo com gráficos ggplot2.
rugarch / fgarch / fseries Variações de modelos GARCH.
VAR / vars / svars VAR, TVAR, SVAR e outras variações.
tsDyn Modelos não-lineares de séries de tempo e com quebras estruturais.
astsa Modelagem de séries de tempo. Pacote que acompanha o livro TSA
TSA Modelagem de séries de tempo. Pacote que acompanha o livro TSA
tseries Teste para séries de tempo (raiz unitária, Ljung-Box, etc.)
Econometria
AER Bases de dados e funções para análise de regressão. Traz consigo os pacotes car e cartest.
mlogit Logit e Probit multinomial.
lmtest Testes usuais para regressões.
gmm Modelos GMM.
nlme / nls Modelos de regressão não-lineares.
stargazer Exporta resultados de regressão para html e LaTeX.
quantreg Regressão quantílica.

Operações entre números

# Operações aritméticas são bastante intuitivas
a <- 3
b <- 5
# Soma
a+b
## [1] 8
# Produto
a*b
## [1] 15
# Subtração
a-b
## [1] -2
# Divisão
a/b
## [1] 0.6
# Exponenciação
a^b
## [1] 243
# Logaritmo natural
log(a)
## [1] 1.098612
# Logartimo (base 10)
log(100, base = 10)
## [1] 2
# Exponencial
exp(a+b)
## [1] 2980.958
# Raiz quadrada
sqrt(a)
## [1] 1.732051

Manipulando vetores

Uma série de tempo univariada \(X(t)\) é uma sequência de observações \(x(1), \, x(2), \, \dots, \, x(n)\) no tempo (\(t = 1, \,2, \, \dots, \, n\)). Formalmente, \[X(t) = [ x(1), \, x(2), \, \dots, \, x(n)]\] pode ser representado como um vetor-coluna (\(n\) linhas e \(1\) coluna). Neste sentido, o objeto matemático que usaremos com mais frequência serão vetores. Ainda que as observações sejam função do tempo é usual denotar o tempo como subscrito, isto é: \[X_{t} = [ x_{1}, \, x_{2}, \, \dots, \, x_{n}]\]

# Construindo um vetor
v <- c(10, 7, 1, 2, 5, 6, 1, 12, 4, pi)
# Apesar de ser interpretado como um vetor coluna, por uma questão de melhor visualização,
# os elementos do vetor são apresentados lado a lado.
print(v)
##  [1] 10.000000  7.000000  1.000000  2.000000  5.000000  6.000000  1.000000
##  [8] 12.000000  4.000000  3.141593
# Média
mean(v)
## [1] 5.114159
# Variância
var(v)
## [1] 13.81371
# 'Comprimento' (equivalente ao número de elementos do vetor)
length(v)
## [1] 10

As operações entre vetores costumam ser definidas apenas entre vetores, isto é, dados dois vetores \(v_{1} = (1,2)\) e \(v_{2} = (3,4)\). Temos que: \[\begin{align} v_{1} + v_{2} = \begin{pmatrix} 1 \\ 2 \end{pmatrix} + \begin{pmatrix} 3 \\ 4 \end{pmatrix} = \begin{pmatrix} 1 + 2\\ 3 + 4 \end{pmatrix} = \begin{pmatrix} 3 \\ 7 \end{pmatrix} \end{align}\]

Naturalmente, o R também opera assim, mas ele também tem algumas comodidades. Em especial, ele trata vetores como se fossem números. Assim, podemos somar vetores com vetores da mesma dimensão, mas também podemos somar um vetor com um número, ou tirar a raiz quadrada de um vetor. Este tipo de operação é feita elemento a elemento. Isto fica claro nos exemplos abaixo:

# Somando
v + 1
##  [1] 11.000000  8.000000  2.000000  3.000000  6.000000  7.000000  2.000000
##  [8] 13.000000  5.000000  4.141593
# Subtraindo
v - 2
##  [1]  8.000000  5.000000 -1.000000  0.000000  3.000000  4.000000 -1.000000
##  [8] 10.000000  2.000000  1.141593
# Multiplicação por escalar
1.5*v
##  [1] 15.000000 10.500000  1.500000  3.000000  7.500000  9.000000  1.500000
##  [8] 18.000000  6.000000  4.712389
# Exponenciação
v^2
##  [1] 100.000000  49.000000   1.000000   4.000000  25.000000  36.000000
##  [7]   1.000000 144.000000  16.000000   9.869604
# Log
log(v)
##  [1] 2.3025851 1.9459101 0.0000000 0.6931472 1.6094379 1.7917595 0.0000000
##  [8] 2.4849066 1.3862944 1.1447299
# Raiz quadrada
sqrt(v)
##  [1] 3.162278 2.645751 1.000000 1.414214 2.236068 2.449490 1.000000
##  [8] 3.464102 2.000000 1.772454
# Soma entre vetores
a <- c(1, 2, 3)
b <- c(2, 4, 6)
a+b
## [1] 3 6 9
# Selecionando valores específicos
v[1]   # primeiro elemento do vetor v
## [1] 10
v[5]   # quinto elemento do vetor v
## [1] 5
b[3]   # terceiro elemento do vetor b
## [1] 6
# Cria vetor a partir de uma sequência
x <- seq(from = 1, to = 10, by = 0.5)
x
##  [1]  1.0  1.5  2.0  2.5  3.0  3.5  4.0  4.5  5.0  5.5  6.0  6.5  7.0  7.5
## [15]  8.0  8.5  9.0  9.5 10.0
# Troca um valor específico
x[2] <- 10

Vetores e séries de tempo

Como \(v\) é um vetor numérico podemos interpretá-lo como uma série de tempo usando o comando ts(), abreviação de “time series”. Adicionalmente, podemos especificar a data de início/fim e a frequência da série como argumentos adicionais no mesmo comando. Em muitos casos, contudo, esta informação não faz diferença na análise e podemos tratar o tempo como \(t = 1, 2, 3, \dots, n\).

vec <- ts(v)
plot.ts(vec, type = 'o')

Criando vetores com funções

Distribuições estatísticas

Em geral, criamos vetores a partir de funções ou de bases de dados. Um método bastante usual é de criar um vetor de números \(x_{1}, x_{2}, \dots x_{n}\) que seguem alguma distribuição - por exemplo, a distribuição normal (gaussiana). Lembre-se que a distribuição normal depende de dois parâmetros: \(\mu\) e \(\sigma\).

# Cria um vetor com 150 observações a partir de uma distribuição normal
x <- rnorm(n = 150, 
           mean = 5, 
           sd = 10)
plot.ts(x, type = 'o')

hist(x)

Outra distribuição comum é a uniforme. Note que eu poderia apenas ter escrito runif(100) para chegar no mesmo resultado.

# Uniforme
x <- runif(n = 100, min = 0, max = 1)
plot.ts(x)

Para uma lista completa das distribuições embutidas no R consulte ?Distributions

Criando vetores com loops

Estruturas recursivas aparecem frequentemente em séries de tempo. Um exemplo simples é: \[\begin{equation} x_{t} = \alpha x_{t-1} + \epsilon_{t}, \quad t = 1, \, \dots, n \end{equation}\] onde \(\alpha\) é igual a uma constante e \(\epsilon_{t}\) segue alguma distribuição, por exemplo, uma normal. Se \(\alpha = 1/2\) e \(\epsilon_{t} \sim \mathcal{N}(0, 1)\) temos que: \[\begin{align} x_{1} & = \frac{1}{2}x_{0} + \epsilon_{1}\\ x_{2} & = \frac{1}{2}x_{1} + \epsilon_{2}\\ \vdots & \\ x_{t} & = \frac{1}{2}x_{t-1} + \epsilon_{t} \end{align}\]

Criar esta série no R é bastante simples, mas é preciso notar alguns detalhes. Primeiro, os objetos do R são indexados por inteiros excluindo o zero. Então o primeiro elemento de vetor x é acessado com x[1]. A ideia do loop é criar um vetor \(\vec{x}\) de tamanho genérico usando c(). A cada passo do loop vamos calcular um valor e colocá-lo no vetor. Isto ficará mais claro no exemplo abaixo.

x <- c()
alfa <- 1/2
x[1] <- 1

for(i in 1:99){
  
  x[i + 1] <- alfa*x[i] + rnorm(n = 1, mean = 0, sd = 1)
  
}

plot.ts(x, type = "o")

O loop acima executa o comando entre chaves para todos valores de \(i\) entre 1 e 99. Isto é, quando \(i = 17\), por exemplo, o código faz: x[18] <- alfa*x[17] + rnorm(1). Ou seja, o elemento 18 deste vetor é substituído por \(\alpha\) vezes o elemento anterior mais um número aleatório sorteado de uma distribuição normal padrão.

minha_funcao <- function(num) {

    x <- c()

    for(i in 1:num) {x[i] <- mean(rnorm(n = i, mean = 5, sd = 20))}

    plot(x, type = "l", xlab = "tamanho da amostra")
}
minha_funcao(500)

Matrizes

Operações elementares entre matrizes

(A <- diag(c(1,2,3,4)))
##      [,1] [,2] [,3] [,4]
## [1,]    1    0    0    0
## [2,]    0    2    0    0
## [3,]    0    0    3    0
## [4,]    0    0    0    4
(B <- matrix(rnorm(n = 16), ncol = 4))
##            [,1]       [,2]       [,3]       [,4]
## [1,] 0.07718727 -0.4650820 -0.7455352  0.1502847
## [2,] 0.78316051  0.8748955 -1.1992318 -0.2237822
## [3,] 1.33957712 -0.7841081  0.9357648 -0.7431865
## [4,] 2.82123912  0.9897210 -0.5677008  1.0245801
(C <- matrix(rep(x = sqrt(2), 8), ncol = 4))
##          [,1]     [,2]     [,3]     [,4]
## [1,] 1.414214 1.414214 1.414214 1.414214
## [2,] 1.414214 1.414214 1.414214 1.414214
(v <- c(1,1,0,1))
## [1] 1 1 0 1
# Operações
A+B
##           [,1]       [,2]       [,3]       [,4]
## [1,] 1.0771873 -0.4650820 -0.7455352  0.1502847
## [2,] 0.7831605  2.8748955 -1.1992318 -0.2237822
## [3,] 1.3395771 -0.7841081  3.9357648 -0.7431865
## [4,] 2.8212391  0.9897210 -0.5677008  5.0245801
A*v
##      [,1] [,2] [,3] [,4]
## [1,]    1    0    0    0
## [2,]    0    2    0    0
## [3,]    0    0    0    0
## [4,]    0    0    0    4
A - 1
##      [,1] [,2] [,3] [,4]
## [1,]    0   -1   -1   -1
## [2,]   -1    1   -1   -1
## [3,]   -1   -1    2   -1
## [4,]   -1   -1   -1    3
#A + C

# Transposta
t(A)
##      [,1] [,2] [,3] [,4]
## [1,]    1    0    0    0
## [2,]    0    2    0    0
## [3,]    0    0    3    0
## [4,]    0    0    0    4
t(A)%*%t(C)
##          [,1]     [,2]
## [1,] 1.414214 1.414214
## [2,] 2.828427 2.828427
## [3,] 4.242641 4.242641
## [4,] 5.656854 5.656854
# Inversa
solve(A)
##      [,1] [,2]      [,3] [,4]
## [1,]    1  0.0 0.0000000 0.00
## [2,]    0  0.5 0.0000000 0.00
## [3,]    0  0.0 0.3333333 0.00
## [4,]    0  0.0 0.0000000 0.25

Matrizes e data.frames

A <- matrix(rnorm(1000), ncol = 2)
nomes <- c("peso", "altura")
dados <- as.data.frame(A)
names(dados) <- nomes

head(dados)
##         peso      altura
## 1 -0.8509591  0.32371029
## 2  0.1912538 -0.83437486
## 3 -0.6900500 -0.05317029
## 4 -0.1606936 -0.55994842
## 5  0.2884652 -1.66458766
## 6 -0.3374655 -1.10775859
colMeans(A)
## [1] -0.007289069  0.012921850

Mínimos Quadrados com matrizes

Seja \(\vec{y}\) um vetor \(n\)x\(1\) e \(X\) uma matriz \(n\)x\(k\)

X <- cbind(1, A)
# Vetor de betas 'verdadeiros'
b <- c(4, 2.5, 3)
# Modelo de MQO
y <- X%*%b + rnorm(n = 500)
# Computa a estimativa dos betas chapéu
(b_hat <- solve(t(X)%*%X)%*%t(X)%*%y)
##          [,1]
## [1,] 3.923847
## [2,] 2.449227
## [3,] 2.984460

Data Frames

O data.frame é como uma tabela com dados; tipicamente, as linhas são observações e as colunas são variáveis. Podemos ter um data.frame em que cada linha é um indivíduo \(i\) e nas \(k\) colunas há variáveis do indivíduo (renda, escolaridade, etc.). O R já vem com alguns data.frames embutidos e a maioria dos pacotes traz consigo algumas bases de dado de exemplo. Também podemos importar tabelas/dados de diversos padrões usando comandos como read_csv. Algumas extensões como o .dta do Stata exigem a instalação de pacotes adicionais; neste caso específico, seria o haven. O RStudio facilita este processo pois permite que se carregue uma base de dados externa apenas “clicando e apontado” e já instala/carrega os pacotes necessários na hora da importação. Nos exemplos abaixo, por comodidade, usaremos apenas dados que já estão carregados no R.

Dica: O comando data() lista todos os conjuntos de dados disponíveis no R. Para uma lista mais específica use data(package = "[nome do pacote]")

Abaixo carrego uma base de dados de consumo de cigarros, discriminados no 50 estados dos EUA. Todas as variáveis estão em log. Na primeira coluna temos o número de pacotes de cigarro por habitante (maior de 16 anos); na segunda coluna temos o preço médio do pacote; na terceira coluna temos a renda disponível média. Os comandos head(), summary() e str() facilitam uma primeira análise dos dados.

  • O comando head() apresenta as primeiras linhas da base, incluindo uma abreviação que indica o tipo da variável. No caso abaixo todas as variáveis são numéricas, em especial, elas são double, de double-precision. Isto indica a precisão numérica do R para armazenar estes valores. Em geral, varáveis númericas são do tipo double (dbl) ou integer (int). O último grupo se refere aos inteiros, isto é, \(0, 1, -1, 2, -2, \dots\), enquanto o primeiro, para finalidades práticas, pode ser entendido como o conjunto dos reais.

  • O comando summary() apresenta estatísticas descritivas simples (média, máximo, mínimo, etc.) das variáveis numéricas de um data.frame. Veremos adiante outros usos desta função.

  • O comando str() apresenta a estrutura dos dados, detalhando a classe de cada variável, o número das observações, etc.

# Pacote que acompanha o livro 'Applied Econometrics with R'
library(AER, quietly = T)
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
# Carregamos uma das bases de dados explorada no livro
data(CigarettesB)
# Obs: para uma lista completa das bases usadas no livro use o comando `data(package = "AER")`
# Obs: para mais detalhes sobre a base use ?CigarettesB
head(CigarettesB)
##      packs   price  income
## AL 4.96213 0.20487 4.64039
## AZ 4.66312 0.16640 4.68389
## AR 5.10709 0.23406 4.59435
## CA 4.50449 0.36399 4.88147
## CT 4.66983 0.32149 5.09472
## DE 5.04705 0.21929 4.87087
summary(CigarettesB)
##      packs           price             income     
##  Min.   :4.409   Min.   :-0.0326   Min.   :4.529  
##  1st Qu.:4.712   1st Qu.: 0.1405   1st Qu.:4.679  
##  Median :4.815   Median : 0.2002   Median :4.759  
##  Mean   :4.848   Mean   : 0.2055   Mean   :4.775  
##  3rd Qu.:4.984   3rd Qu.: 0.2735   3rd Qu.:4.853  
##  Max.   :5.379   Max.   : 0.3640   Max.   :5.103
str(CigarettesB)
## 'data.frame':    46 obs. of  3 variables:
##  $ packs : num  4.96 4.66 5.11 4.5 4.67 ...
##  $ price : num  0.205 0.166 0.234 0.364 0.321 ...
##  $ income: num  4.64 4.68 4.59 4.88 5.09 ...

Um valor num data.frame é unicamente determinado por um par \([i,j]\) assim como numa matriz. Isto é, no exemplo acima podemos estar interessados no valor que está na quinta linha da segunda coluna. Este é o elemento \([5,2]\). Também é possível acessar os valores de uma (ou mais) colunas de um data.frame deixando o valor da linha \(i\) em branco, isto é, \([, 2]\) faz referência à segunda coluna de um data.frame. Analogamente, podemos fazer o mesmo, deixando vazia a casa das colunas para acessar todos os valores de um subconjunto de linhas. Vamos deixar estes conceitos mais claros com um exemplo.

X <- data.frame(nasc = c(1888, 1889, 1890, 1887),
                mort = c(1935, 1915, 1935, NA),
                nome = c("Fernando Pessoa", "Álvaro de Campos", "Alberto Caeiro", "Ricardo Reis"),
                tipo = c("Ele mesmo", rep("Heterônimo", 3))
                )
X
##   nasc mort             nome       tipo
## 1 1888 1935  Fernando Pessoa  Ele mesmo
## 2 1889 1915 Álvaro de Campos Heterônimo
## 3 1890 1935   Alberto Caeiro Heterônimo
## 4 1887   NA     Ricardo Reis Heterônimo

Acessando valores específicos

# 
X[1, 2]
## [1] 1935
# O ano de morte de Ricardo Reis 
# NA significa Not Applicable; neste contexto se refere à uma observação ausente
# pois não há uma data oficial para o ano de morte de Ricardo Reis)

X[4, 2]
## [1] NA
#
X[, 3]
## [1] Fernando Pessoa  Álvaro de Campos Alberto Caeiro   Ricardo Reis    
## 4 Levels: Alberto Caeiro Álvaro de Campos ... Ricardo Reis
X$nome
## [1] Fernando Pessoa  Álvaro de Campos Alberto Caeiro   Ricardo Reis    
## 4 Levels: Alberto Caeiro Álvaro de Campos ... Ricardo Reis
#
X[c(2,3), 2:4]
##   mort             nome       tipo
## 2 1915 Álvaro de Campos Heterônimo
## 3 1935   Alberto Caeiro Heterônimo

Juntando tabelas

Para tabelas de dimensões apropriadas podemos utilizar os comandos cbind() e rbind().

cbind(X, c(1,2,3,4))
##   nasc mort             nome       tipo c(1, 2, 3, 4)
## 1 1888 1935  Fernando Pessoa  Ele mesmo             1
## 2 1889 1915 Álvaro de Campos Heterônimo             2
## 3 1890 1935   Alberto Caeiro Heterônimo             3
## 4 1887   NA     Ricardo Reis Heterônimo             4
rbind(X, c())
##   nasc mort             nome       tipo
## 1 1888 1935  Fernando Pessoa  Ele mesmo
## 2 1889 1915 Álvaro de Campos Heterônimo
## 3 1890 1935   Alberto Caeiro Heterônimo
## 4 1887   NA     Ricardo Reis Heterônimo

Para casos mais complexos vale a pena usar as funções _join() do pacote dplyr().

library(dplyr, quietly = TRUE)
## 
## Attaching package: 'dplyr'
## The following object is masked from 'package:car':
## 
##     recode
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
p <- c('Mar Português', 'Ela canta, pobre ceifeira', 'Hora absurda',
       'Tabacaria', 'Lisbon Revisited', 'Poema em Linha Reta',
       'O amor é uma companhia', 'XX - O Tejo ...', 'Leve, leve, muito leve,',
       'Boi Morto', 'Estrela da Manhã', 'Chama e Fumo')
poemas <- 
  data.frame(
  
  autor = c(rep("Fernando Pessoa", 3), rep("Álvaro de Campos", 3),
            rep("Alberto Caeiro",  3), rep("Manuel Bandeira",     3)
            ),
  poema = p
  
  )

left_join (poemas, X, by = c('autor' = 'nome'))
##               autor                     poema nasc mort       tipo
## 1   Fernando Pessoa             Mar Português 1888 1935  Ele mesmo
## 2   Fernando Pessoa Ela canta, pobre ceifeira 1888 1935  Ele mesmo
## 3   Fernando Pessoa              Hora absurda 1888 1935  Ele mesmo
## 4  Álvaro de Campos                 Tabacaria 1889 1915 Heterônimo
## 5  Álvaro de Campos          Lisbon Revisited 1889 1915 Heterônimo
## 6  Álvaro de Campos       Poema em Linha Reta 1889 1915 Heterônimo
## 7    Alberto Caeiro    O amor é uma companhia 1890 1935 Heterônimo
## 8    Alberto Caeiro           XX - O Tejo ... 1890 1935 Heterônimo
## 9    Alberto Caeiro   Leve, leve, muito leve, 1890 1935 Heterônimo
## 10  Manuel Bandeira                 Boi Morto   NA   NA       <NA>
## 11  Manuel Bandeira          Estrela da Manhã   NA   NA       <NA>
## 12  Manuel Bandeira              Chama e Fumo   NA   NA       <NA>
right_join(poemas, X, by = c('autor' = 'nome'))
##               autor                     poema nasc mort       tipo
## 1   Fernando Pessoa             Mar Português 1888 1935  Ele mesmo
## 2   Fernando Pessoa Ela canta, pobre ceifeira 1888 1935  Ele mesmo
## 3   Fernando Pessoa              Hora absurda 1888 1935  Ele mesmo
## 4  Álvaro de Campos                 Tabacaria 1889 1915 Heterônimo
## 5  Álvaro de Campos          Lisbon Revisited 1889 1915 Heterônimo
## 6  Álvaro de Campos       Poema em Linha Reta 1889 1915 Heterônimo
## 7    Alberto Caeiro    O amor é uma companhia 1890 1935 Heterônimo
## 8    Alberto Caeiro           XX - O Tejo ... 1890 1935 Heterônimo
## 9    Alberto Caeiro   Leve, leve, muito leve, 1890 1935 Heterônimo
## 10     Ricardo Reis                      <NA> 1887   NA Heterônimo
inner_join(poemas, X, by = c('autor' = 'nome'))
##              autor                     poema nasc mort       tipo
## 1  Fernando Pessoa             Mar Português 1888 1935  Ele mesmo
## 2  Fernando Pessoa Ela canta, pobre ceifeira 1888 1935  Ele mesmo
## 3  Fernando Pessoa              Hora absurda 1888 1935  Ele mesmo
## 4 Álvaro de Campos                 Tabacaria 1889 1915 Heterônimo
## 5 Álvaro de Campos          Lisbon Revisited 1889 1915 Heterônimo
## 6 Álvaro de Campos       Poema em Linha Reta 1889 1915 Heterônimo
## 7   Alberto Caeiro    O amor é uma companhia 1890 1935 Heterônimo
## 8   Alberto Caeiro           XX - O Tejo ... 1890 1935 Heterônimo
## 9   Alberto Caeiro   Leve, leve, muito leve, 1890 1935 Heterônimo
anti_join(poemas, X, by = c('autor' = 'nome'))
##             autor            poema
## 1 Manuel Bandeira        Boi Morto
## 2 Manuel Bandeira Estrela da Manhã
## 3 Manuel Bandeira     Chama e Fumo

Alterando atributos

# Renomeando as variáveis
names(X) <- c("Ano de nascimento", "Ano de morte", "Nome", "Tipo")
# Agregações

Gráficos

O R tem uma função de funcionalidade geral para exibir gráficos: plot(). Em alguns contextos de séries de tempo pode ser mais conveniente usar as alternativas plot.ts() ou ts.plot().

Gráfico de dispersão

Para visualizar a relação entre os dados podemos fazer gráficos de dispersão. A lógica da sintaxe é bastante simples y ~ x onde y seria como a variável explicada e x a variável explicativa.

d <- CigarettesB
plot(packs ~ price, data = d)

Outra forma de chegar no mesmo resultado é chamando os vetores numéricos, isto é, usando d$packs ou d[, 1]

plot(x = d$price, y = d$packs)

plot(x = d$price,
     y = d$packs,
     main = "titulo do gráfico",
     sub  = "subtítulo",
     xlab = "nome do eixo x",
     ylab = "nome do eixo y",
     )

Gráfico de linha

Para representar visualmente uma série de tempo usamos gráficos de linha. Podemos fazer isto apenas alterando o argumento type na função plot.

x <- rnorm(n = 20)
plot(x, type = "l")

A função plot.ts eventualmente pode ser mais conveniente pois dispensa a necessidade de especificar o tipo do gráfico.

plot.ts(x)

Note, contudo, que objetos ts são automaticamente interpretados como séries de tempo.

class(AirPassengers)
## [1] "ts"
plot(AirPassengers)

Também podemos inserir linhas num gráfico usando as funções lines() e abline(). A primeira é mais indicada para inserir uma série de tempo num gráfico, enquanto a última é mais indicada para “desenhar linhas retas”. O exemplo abaixo mostra isto. Criamos \(y = \text{cos}(x)\) e \(z = \text{cos}(x) + 2 + 0.1x\), onde \(x \in [0, 4\pi]\). A série \(z\) é adicionada usando a função \(lines()\); duas linhas retas são traçadas usando a função abline(). Esta função exige argumentos a e b que representam os coeficientes da equação \(y = a + bx\), isto é, a é o intercepto e b é a inclinação.

x <- seq(from = 0, to = 4*pi, by = 0.01)
y <- cos(x)
z <- cos(x) + 2 + 0.1*x

plot(x = x, y = y, ylim = c(-1, 4), type = "l")
lines(x = x, y = z, col = "blue")
abline(a = 0, b = 0, col = "black")
abline(a = 2, b = 0.1, col = "blue")

x <- c(0)
for(i in 1:50){

    x[i + 1] <- x[i] + 0.2 + rnorm(n = 1)

}

plot.ts(x)

abline(a = 0, b = .2, lty = 2)

Quando temos um objeto com várias séries de tempo podemos

ts.plot(ldeaths, mdeaths, fdeaths,
        gpars = list(xlab = "year", ylab = "deaths", lty = c(1, 2, 3)))

X <- matrix(0, ncol = 20, nrow = 50)

for(j in 1:20){
    for(i in 1:49){

        X[i + 1, j] <- (3/4) * X[i, j] + rnorm(n = 1)

    }
}

ts.plot(X, col = rainbow(20), ylim = c(-5, 5))

Histograma

hist(d$income)

hist(d$income, freq = FALSE)

plot(density(d$income))

normalizado <- scale(d$income)
x <- seq(from = -4, to = 4, by = 0.1)
hist(normalizado, freq = FALSE)
lines(x, dnorm(x), 
      col = "blue",
      lwd = 3)

Gráfico de barras

Para fazer gráficos de barras/colunas usamos a função barplot()

cat <- c("A", "B", "C")
val <- c(2, 4.5, 3)
barplot(val, names.arg = cat)

barplot(VADeaths)

barplot(VADeaths, beside = TRUE)

mp <- barplot(VADeaths)
tot <- colMeans(VADeaths)
text(mp, tot + 3, format(tot), xpd = TRUE, col = "blue")

barplot(VADeaths, beside = TRUE,
        col = c("lightblue", "mistyrose", "lightcyan",
                "lavender", "cornsilk"),
        legend = rownames(VADeaths), ylim = c(0, 100))
title(main = "Death Rates in Virginia", font.main = 4)

Regressão linear

summary(fit <- lm(packs ~ price, data = d))
## 
## Call:
## lm(formula = packs ~ price, data = d)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.45472 -0.09968  0.00612  0.11553  0.29346 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   5.0941     0.0627  81.247  < 2e-16 ***
## price        -1.1983     0.2818  -4.253 0.000108 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.163 on 44 degrees of freedom
## Multiple R-squared:  0.2913, Adjusted R-squared:  0.2752 
## F-statistic: 18.08 on 1 and 44 DF,  p-value: 0.0001085
class(fit)
## [1] "lm"
coef(fit)
## (Intercept)       price 
##    5.094108   -1.198316
confint(fit, level = 0.95)
##                 2.5 %     97.5 %
## (Intercept)  4.967747  5.2204696
## price       -1.766224 -0.6304087
plot(fit)

plot(packs ~ price, data = d)
abline(coef(fit))

data(MurderRates)
head(MurderRates)
##    rate convictions executions time income  lfp noncauc southern
## 1 19.25       0.204      0.035   47   1.10 51.2   0.321      yes
## 2  7.53       0.327      0.081   58   0.92 48.5   0.224      yes
## 3  5.66       0.401      0.012   82   1.72 50.8   0.127       no
## 4  3.21       0.318      0.070  100   2.18 54.4   0.063       no
## 5  2.80       0.350      0.062  222   1.75 52.4   0.021       no
## 6  1.41       0.283      0.100  164   2.26 56.7   0.027       no
summary(fit <- lm(rate ~ . , data = MurderRates))
## 
## Call:
## lm(formula = rate ~ ., data = MurderRates)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -4.9913 -1.1943 -0.3538  1.2383  6.5574 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)  
## (Intercept)  0.44436    9.96694   0.045   0.9647  
## convictions -4.33938    2.78313  -1.559   0.1277  
## executions   2.85276    6.12313   0.466   0.6441  
## time        -0.01547    0.00705  -2.194   0.0348 *
## income      -2.50013    1.68519  -1.484   0.1466  
## lfp          0.19357    0.20614   0.939   0.3540  
## noncauc     10.39903    5.40610   1.924   0.0623 .
## southernyes  3.26216    1.32980   2.453   0.0191 *
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.459 on 36 degrees of freedom
## Multiple R-squared:  0.7459, Adjusted R-squared:  0.6965 
## F-statistic:  15.1 on 7 and 36 DF,  p-value: 5.105e-09