Um joalheiro precifica os diamantes com base na qualidade, com valores de 0 a 8, sendo 8 perfeito e 0 contendo numerosas imperfeições e cor, com valores de 1 a 10, sendo 10 branco puro e 1 amarelo. Com base no preço por quilate, em centenas de dólares, dos 11 diamantes a seguir, pesando entre 1.0 e 1.5 quilates.
Determinar a relação entre qualidade (quality), cor (color) e preço (price).
Observe que o preço do diamante é a resposta; isto deve-se à que a cor e qualidade são características naturais.
Color = c(7,3,5,8,9,5,4,2,8,6,9) # color do diamante, entre 1 e 10
Quality = c(5,7,8,1,3,4,0,6,7,4,2) # qualidade do diamante, entre 0 e 8
Price = c(65,38,51,38,55,43,25,33,71,51,49) # preço por quilate, em centenas de dólares
dados = data.frame(Color,Quality,Price)
Primeiro uma análise descritiva dos dados.
library(ggplot2)
g1 = ggplot(data = dados, aes(x = Quality, y = Price)) + geom_point()
g2 = ggplot(data = dados, aes(x = Color, y = Price)) + geom_point()
library(patchwork)
g1 + g2
Não visualizamos muito nas figuras acima. Fazeremos transformações nas variáveis explicativas.
g3 = ggplot(data = dados, aes(x = exp(Quality), y = Price)) + geom_point()
g4 = ggplot(data = dados, aes(x = I(Quality*Color), y = Price)) + geom_point()
(g1 + g2) / (g3 + g4)
Observamos que a interação Quality X Color induz uma excelente explicação do Price (preço). Nosso objetivo é mostrar diferentes métodos de diagnóstico; por isso não incliremos numa primeira análise a descoberta anteriormente mencionada.
modelo0 = lm(Price ~ Quality + Color, data = dados)
summary(modelo0)
##
## Call:
## lm(formula = Price ~ Quality + Color, data = dados)
##
## Residuals:
## Min 1Q Median 3Q Max
## -6.672 -4.536 -1.093 3.722 10.190
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.7514 6.9602 0.252 0.807670
## Quality 3.7584 0.7565 4.968 0.001096 **
## Color 4.8953 0.8202 5.968 0.000335 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 5.888 on 8 degrees of freedom
## Multiple R-squared: 0.8507, Adjusted R-squared: 0.8134
## F-statistic: 22.79 on 2 and 8 DF, p-value: 0.0004969
library(car)
influenceIndexPlot(modelo0)
Lembremos que, num modelo linear, Uma medida da influência de cada observação nas estimativas dos parâmetros da regressão é a distância de Cook, dada por \[\begin{equation*} C_i = \frac{1}{p}(\widehat{\beta}-\widehat{\beta}_{(i)})^\top X^\top X (\widehat{\beta}-\widehat{\beta}_{(i)}), \end{equation*}\] onde \(\widehat{\beta}_{(i)}\) são as estimativas dos parâmetros retirando da amostra a \(i\)-ésima observação.
residualPlots(modelo0)
## Test stat Pr(>|Test stat|)
## Quality -1.0163 0.3433
## Color -1.2601 0.2480
## Tukey test 0.9662 0.3340
marginalModelPlots(modelo0)
library(ggfortify)
autoplot(modelo0)
A observação 1 apresentam forte influência no resíduo e a observação 7 é de alta alavancagem (hat-value). Nesta situação não é uma opção a retirada de amostras, a final temos somente 11 observações.
residuos = residuals(modelo0, type="pearson")
summary(residuos)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -6.672 -4.536 -1.092 0.000 3.722 10.190
sd(residuos)
## [1] 5.266463
plot(density(residuos), ylab = "Densidade estimada", main ="", xlim = c(-15,15), ylim = c(0,0.08))
grid()
rug(residuos, lwd = 2)
curve(dnorm(x, mean = mean(residuos), sd = sd(residuos)), add = TRUE, col = "red", lwd = 2)
Embora parecidas estas curvas, deveriamos observar uma amostra normal padrão. A curva em vermelho é a densidade normal de média \(\overline{x}=0.000\) e desvio padrão \(s=5.266463\). Isso significaria que os resíduos deveriam estar no intervalo (-3,3), não apresentar valos tão extremos e o desvio padrão deveria ser aproximadamente 1. Observemos as mesmas curvas agora com os resíduos estudentizados.
residuos = rstandard(modelo0)
summary(residuos)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -1.323630 -0.908229 -0.233398 -0.006416 0.831506 1.852916
sd(residuos)
## [1] 1.029432
plot(density(residuos), ylab = "Densidade estimada", main ="", xlim = c(-3,3), ylim = c(0,0.4))
grid()
rug(residuos, lwd = 2)
curve(dnorm(x, mean = mean(residuos), sd = sd(residuos)), add = TRUE, col = "red", lwd = 2)
É claro que alguma coisa está errada no modelo. Devemos lembrar que, Como qualquer modelo estatístico devemos fazer certas suposições para poder obtermos estimadores, realizar testes de hipóteses de interesse e verificarmos a adequação deste modelo aos dados, a final, a utilidade de qualquer modelo é sua qualidade em representar os dados.
Um modelo de regressão linear deve satisfazer as seguintes suposições:
dados1 = cbind(dados, Prod = I(Quality*Color))
modelo1 = update(modelo0, . ~ . + Prod, data = dados1)
summary(modelo1)
##
## Call:
## lm(formula = Price ~ Quality + Color + Prod, data = dados1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -5.0747 -2.4493 -0.4417 1.2411 7.9992
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 20.2071 8.1325 2.485 0.0419 *
## Quality -0.3012 1.5086 -0.200 0.8474
## Color 1.8313 1.2154 1.507 0.1756
## Prod 0.7280 0.2522 2.887 0.0234 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 4.253 on 7 degrees of freedom
## Multiple R-squared: 0.9318, Adjusted R-squared: 0.9026
## F-statistic: 31.9 on 3 and 7 DF, p-value: 0.0001872
influenceIndexPlot(modelo1)
residuos = rstudent(modelo1)
summary(residuos)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -1.57610 -0.82120 -0.11225 -0.05373 0.36452 3.00850
sd(residuos)
## [1] 1.287887
plot(density(residuos), ylab = "Densidade estimada", main ="", xlim = c(-5,5), ylim = c(0,0.4))
grid()
rug(residuos, lwd = 2)
curve(dnorm(x, mean = mean(residuos), sd = sd(residuos)), add = TRUE, col = "red", lwd = 2)
library(qqplotr); library(ggplot2)
# p-p plot
gg = ggplot(data = data.frame(residuos),
mapping = aes(sample = residuos)) +
stat_pp_band() +
stat_pp_line() +
stat_pp_point() +
labs(x = "Função de distribuição empírica",
y = "Função de distribuição Normal padrão")
# q-q plot
gg1 = ggplot(data = data.frame(residuos),
mapping = aes(sample = residuos)) +
stat_qq_band() +
stat_qq_line() +
stat_qq_point() +
labs(x = "Quantis teóricos", y = "Quantis amostrais")
gg + gg1
Continuamos observando a influência das observações 1 e 7, mas o comportamento dos resíduos Pearson melhorou bastante.
# Teste Anderson-Darling de normalidade
library(DescTools)
AndersonDarlingTest(residuos, null = "pnorm", mean=0, sd=1)
##
## Anderson-Darling test of goodness-of-fit
## Null hypothesis: Normal distribution
## with parameters mean = 0.000, sd = 1.000
##
## data: residuos
## An = 0.62322, p-value = 0.6224
O teste de normalidade aceita esta hipóteses assim como nós aceitamos que todas as suposições do nomelo são cumpridas. São estas as afirmações que podemos tomar com o estudo dos resíduos.
Para avaliarmos a qualidade do ajuste utilizamos o coeficiente de determinação \(R^2\), o qual é amplamente favorável ao modelo reservado no objeto R modelo1.
AIC(modelo0,modelo1)
## df AIC
## modelo0 4 74.71813
## modelo1 5 68.09161
Também escolhemos o modelo em modelo1 utilizando o Critériio AIC. Mostramos agora os dados observados e os valores preditos.
plot(modelo1$model$Price,modelo1$fitted.values, xlab = "Price", ylab = "Valores preditos",
ylim = c(20,80), pch = 19)
grid()
Uma apresentação mais aprimorada seria a seguinte:
pred.int = predict(modelo1, interval = "prediction") # adicionando predições aos dados
mydados = cbind(dados1, pred.int) # reta de regressão + intervalos confidenciais
p <- ggplot(mydados, aes(Price,fit)) + ylab("Valores preditos") + ylim(c(20,80)) +
geom_point() +
stat_smooth(method = lm)
# 3. Add prediction intervals
p + geom_line(aes(y = lwr), color = "red", linetype = "dashed")+
geom_line(aes(y = upr), color = "red", linetype = "dashed")