O R possui pré-instalado diversos conjuntos de dados (datasets) para utilização direta pelo usuário (sem necessidade de importação). Entre com o seguinte comando para visualizar as opções disponíveis:
utils::data()Para o nosso exemplo de regressão linear simples em R usaremos o conjunto de dados “cars”. Ele é composto por 50 observações da velocidade de diferentes carros da década de 20 e da respectiva distância alcançada pelo carros durante o experimento.
str(cars) # Retorna a estrutura do conjunto de dados.## 'data.frame': 50 obs. of 2 variables:
## $ speed: num 4 4 7 7 8 9 10 10 10 11 ...
## $ dist : num 2 10 4 22 16 10 18 26 34 17 ...
Antes de ajustar qualquer modelo, vamos observar o comportamento dos dados com base em algumas técnicas exploratórias gráficas e parâmetros estatísticos. Com a função stat.desc do pacote pastecs podemos verificar estimativas para a média, mediana, range, variância, dentre outros.
library(pastecs)
stat.desc(cars)## speed dist
## nbr.val 50.0000000 50.0000000
## nbr.null 0.0000000 0.0000000
## nbr.na 0.0000000 0.0000000
## min 4.0000000 2.0000000
## max 25.0000000 120.0000000
## range 21.0000000 118.0000000
## sum 770.0000000 2149.0000000
## median 15.0000000 36.0000000
## mean 15.4000000 42.9800000
## SE.mean 0.7477858 3.6443403
## CI.mean.0.95 1.5027319 7.3235761
## var 27.9591837 664.0608163
## std.dev 5.2876444 25.7693775
## coef.var 0.3433535 0.5995667
Neste momento, os valores tabelados acima não nos agregaram mais informações do que visualizando, propriamente dito, os dados. Se queremos um modelo, é esperado que a variável resposta e as preditores possuam uma boa correlação entre si. Para isso, plotemos os valores de velocidade contra as distâncias:
par(mar = c(5,4,2,2))
plot(x = cars$speed,
y = cars$dist,
xlab = "Velocidade (mph)",
ylab = "distância (ft)",
pch = 16)O gráfico acima apresenta uma boa relação entre a velocidade do carro e a distância percorrida por eles no experimento. O coeficiente de correlação de pearson concorda com o gráfico, obtendo um valor igual a 0.8068949.
No código acima usamos o argumento pch para a plotagem dos dados. Este argumento seleciona o formato do simbolo plotado. No gráfico abaixo, tem-se o simbolo associado a cada valor de pch:
Para a construção dos histogramas abaixo usamos o argumento mfrow dentro da função par. Esta última controla todos os argumentos gráficos, enquanto mfrow define a organização de múltiplos gráficos num mesmo painel semelhante a uma matriz. Neste caso nosso painel tem uma linha e duas colunas.
par(mfrow = c(1, 2))
# histograma das velocidades
hist(x = cars$speed,
col = "gray",
xlab = "Velocidade (mph)",
ylab = "Frequência",
main = "")
# histograma das distâncias
hist(x = cars$dist,
col = "lightblue",
xlab = "Distância (ft)",
ylab = "Frequência",
main = "")Com os boxplots abaixo, observamos um possível ponto aberrante (outlier) em nossos dados. Em geral, estamos acostumados com a ideia de um outlier em modelo, ou seja, alguma observação (dados) que o nosso modelo não tem boa aderência e por isso produz um alto resíduo. Não é este o caso.
par(mar = c(4,4,2,2))
# boxplot dos dados de velocidade e distância
boxplot(cars$speed, cars$dist,
names = c("Velocidade", "Distância"),
col = c("lightgray", "lightblue"))Este possível outlier corresponde à observação 49 no conjunto de dados, na qual um carro com velocidade igual a 24 mph alcança 120 ft. Devemos remover este ponto de nossos dados? Para isso devemos perguntar: Esta observação representa nosso conjunto de dados? Estamos tratando de um mesmo tipo de carro? Ou será que ele alcança uma distância menor porque é na realidade um carro de corrida e não um carro urbano? Infelizmente, não temos essa informação. Então, de forma conservadora, vamos manter essa observação em nosso conjunto de dados.
Para construção de nosso modelo \(distancia = \alpha.velocidade + \beta\) vamos utilizar a função nativa do R lm (do inglês, linear model). Nela escrevemos a equação anterior com a seguinte sintaxe: Y ~ X. Ou seja, Y é nossa variável resposta (distância) e X nossa preditora (velocidade). o simbolo “~” equivale a dizer “é função de”. A função lm, então estima o coeficiente da variável preditora e a constante da função por padrão.
modelo.simples = lm(cars$dist ~ cars$speed)
summary(modelo.simples)##
## Call:
## lm(formula = cars$dist ~ cars$speed)
##
## Residuals:
## Min 1Q Median 3Q Max
## -29.069 -9.525 -2.272 9.215 43.201
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -17.5791 6.7584 -2.601 0.0123 *
## cars$speed 3.9324 0.4155 9.464 1.49e-12 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 15.38 on 48 degrees of freedom
## Multiple R-squared: 0.6511, Adjusted R-squared: 0.6438
## F-statistic: 89.57 on 1 and 48 DF, p-value: 1.49e-12
A função retorna no console (acima) diversas informações sobre o modelo e sua adequação.
Na linha Call temos a função ajustada pela função lm. Na linha Residual são apresentadas algumas informações sobre os resíduos do modelo (valor mínimo, máximo, mediana, 1° e 3° Quartis).
Na linha Coeficients é apresentada uma tabela contendo o valor dos coeficientes (Estimate), o erro padrão do coeficiente (Std. Error), o valor da estatística t (t value) e finalmente o p-valor do teste t para significância do coeficiente (Pr(>|t|)).
Ao lado direito do p-valor do teste dos coeficientes, ainda é apresentado por meio de símbolos (explicados na linha abaixo), para qual nível de significância os coeficientes são significativos.
Por fim, é realizado um teste F para adequação do modelo, apresentado para isso o número de graus de liberdade envolvidos, o erro padrão residual, os valores para o R2 e o R2 ajustado, o consequente valor da estatística F e seu respectivo p-valor. Caso deseje-se obter a tabela de ANOVA separadamente, basta entrar com a função:
anova(modelo.simples)## Analysis of Variance Table
##
## Response: cars$dist
## Df Sum Sq Mean Sq F value Pr(>F)
## cars$speed 1 21186 21185.5 89.567 1.49e-12 ***
## Residuals 48 11354 236.5
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Com base nas informações acima, podemos afirmar que o modelo é estatisticamente significante (p-valor do teste F aproximadamente nulo), da mesma forma que com os coeficientes de regressão (p-valor do teste T). O valor do R2 indica um aderência moderada aos dados (~ 0.6).
Contudo, o que garante que as conclusões anteriores sejam verdadeiras? A estimativa dos p-valores, do R2 e dos coeficientes é em sua essência uma função matemática, independente dos valores utilizados, um resultado será obtido. Então, o que garante os resultados tenham valor estatístico?
Resposta: O cumprimento das considerações do modelo de mínimos quadrados:
Estas condições vem do desenvolvimento do métodos dos mínimos quadrados a partir do método da máxima verossimilhança e devem ser avaliados a posteriori da construção do modelo.
Inicialmente, avaliemos a hipótese de homoscedasticidade dos resíduos de forma gráfica, plotando os valores preditos pelo modelo por aqueles observados (distância).
par(mar = c(5,4,2,2))
plot(x = cars$dist,
y = modelo.simples$fitted.values,
xlim = c(0, 120),
ylim = c(0, 120),
pch = 16,
xlab = "Valores observados",
ylab = "Valores preditos")
abline(a = 0, b = 1, lty = 2, col = "red")Com base no gráfico anterior, verifica-se que para valores acima de 80 para a distância, a predição do modelo começa a ser prejudicada, estimando valores menores do que o observado. Observe também que o modelo pode estimar valores negativos para a distância quando valores baixos de velocidade são utilizados, o que compromete o domínio de aplicação do modelo.
A mesma conclusão pode ser obtida avaliando o gráfico a direta no painel a seguir. À esquerda, no gráfico de resíduos versus a variável preditora, por outro lado, não se encontra indícios visuais da não-aleatoriedade dos resíduos.
par(mfrow = c(1, 2), mar = c(5,4,2,2))
plot(x = cars$speed,
y = modelo.simples$residuals,
pch = 16,
col = "red",
xlab = "Velocidade (mph)", ylab = "Resíduos")
plot(x = cars$dist,
y = modelo.simples$residuals,
pch = 16,
col = "lightblue",
xlab = "Distância (ft)", ylab = "Resíduos")A distribuição de probabilidade dos resíduos pode ser verificada visualmente a partir de um histograma dos resíduos. Que conforme a figura abaixo indica uma cauda não simétrica a direita da distribuição, o que sugere a não normalidade dos resíduos.
par(mar = c(5,4,2,2))
hist(x = modelo.simples$residuals,
xlab = "Resíduos",
ylab = "Densidade de Probabilidade",
main = "",
col = "lightgreen",
probability = TRUE)
lines(density(modelo.simples$residuals))Aplicando o teste de Shapiro-Wilk para os resíduos (shapiro.test), concluímos que para um nível de significância de 5%, nossos dados não vêm de uma distribuição normal.
shapiro.test(modelo.simples$residuals)##
## Shapiro-Wilk normality test
##
## data: modelo.simples$residuals
## W = 0.94509, p-value = 0.02152
A validação do modelo demonstrou até certo ponto que as considerações necessárias para o método dos mínimos quadrados não foram atendidos. Aplicabilidade e significância estatística, são, contudo, aspectos diferentes.
A validação não é finalizada apenas com estas análises, técnicas como a chamada “crossvalidation” ainda podem ser aplicadas.
Outra questão interessante a ser discutida é a robustez dos teste estatísticos (F e t) contra a fuga da normalidade ou aleatoriedade dos resíduos.