O ficheiro https://web.tecnico.ulisboa.pt/paulo.soares/iadme/dados/penguins.csv (14.9KB) contém observações feitas entre 2007 e 2009 em pinguins adultos de três espécies que se encontram em três ilhas do Arquipélago de Palmer na Antártida.
As variáveis incluídas no conjunto de dados são as seguintes:
| Variável | Descrição |
|---|---|
species |
espécie (Adelie, Chinstrap ou Gentoo) |
island |
ilha (Biscoe, Dream ou Torgersen) |
bill_len |
comprimento do bico (mm) |
bill_dep |
altura do bico (mm) |
flipper_len |
comprimento das asas (usadas como barbatanas, claro!) (mm) |
body_mass |
massa corporal (g) |
sex |
sexo (female ou male) |
year |
ano do estudo (2007, 2008 ou 2009) |
Referência: Gorman, K. B., Williams, T. D. and Fraser, W. R. (2014) Ecological Sexual Dimorphism and Environmental Variability within a Community of Antarctic Penguins (Genus Pygoscelis). PLoS ONE 9, 3, e90081; doi:10.1371/journal.pone.0090081.
Leia o ficheiro de dados no R e transforme todas as variáveis de tipo character em fatores.
Em quantas observações há dados em falta?
library(dplyr)
url <- "https://web.tecnico.ulisboa.pt/paulo.soares/iadme/dados/penguins.csv"
pinguins <- read.csv(url)
str(pinguins)
## 'data.frame': 344 obs. of 8 variables:
## $ species : chr "Adelie" "Adelie" "Adelie" "Adelie" ...
## $ island : chr "Torgersen" "Torgersen" "Torgersen" "Torgersen" ...
## $ bill_len : num 39.1 39.5 40.3 NA 36.7 39.3 38.9 39.2 34.1 42 ...
## $ bill_dep : num 18.7 17.4 18 NA 19.3 20.6 17.8 19.6 18.1 20.2 ...
## $ flipper_len: int 181 186 195 NA 193 190 181 195 193 190 ...
## $ body_mass : int 3750 3800 3250 NA 3450 3650 3625 4675 3475 4250 ...
## $ sex : chr "male" "female" "female" NA ...
## $ year : int 2007 2007 2007 2007 2007 2007 2007 2007 2007 2007 ...
pinguins |>
mutate(across(where(is.character), as.factor)) ->
pinguins
str(pinguins)
## 'data.frame': 344 obs. of 8 variables:
## $ species : Factor w/ 3 levels "Adelie","Chinstrap",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ island : Factor w/ 3 levels "Biscoe","Dream",..: 3 3 3 3 3 3 3 3 3 3 ...
## $ bill_len : num 39.1 39.5 40.3 NA 36.7 39.3 38.9 39.2 34.1 42 ...
## $ bill_dep : num 18.7 17.4 18 NA 19.3 20.6 17.8 19.6 18.1 20.2 ...
## $ flipper_len: int 181 186 195 NA 193 190 181 195 193 190 ...
## $ body_mass : int 3750 3800 3250 NA 3450 3650 3625 4675 3475 4250 ...
## $ sex : Factor w/ 2 levels "female","male": 2 1 1 NA 1 2 1 2 NA NA ...
## $ year : int 2007 2007 2007 2007 2007 2007 2007 2007 2007 2007 ...
pinguins$num_vars_falta <- rowSums(is.na(pinguins))
solution <- sum(pinguins$num_vars_falta > 0)
O valor pretendido é 11.
Elimine as observações em que faltem valores em mais do que uma variável. Em seguida, confirme que apenas faltam valores na variável sex e substitua esses valores em falta por “female”.
Indique o rácio de pinguins fêmeas por macho no conjunto de dados final.
pinguins |>
filter(num_vars_falta < 2) ->
pinguins
pinguins$num_vars_falta <- NULL
summary(pinguins)
## species island bill_len bill_dep
## Adelie :151 Biscoe :167 Min. :32.1 Min. :13.1
## Chinstrap: 68 Dream :124 1st Qu.:39.2 1st Qu.:15.6
## Gentoo :123 Torgersen: 51 Median :44.5 Median :17.3
## Mean :43.9 Mean :17.2
## 3rd Qu.:48.5 3rd Qu.:18.7
## Max. :59.6 Max. :21.5
## flipper_len body_mass sex year
## Min. :172 Min. :2700 female:165 Min. :2007
## 1st Qu.:190 1st Qu.:3550 male :168 1st Qu.:2007
## Median :197 Median :4050 NA's : 9 Median :2008
## Mean :201 Mean :4202 Mean :2008
## 3rd Qu.:213 3rd Qu.:4750 3rd Qu.:2009
## Max. :231 Max. :6300 Max. :2009
# # Por exemplo:
# sexo_em_falta <- "male"
pinguins |>
tidyr::replace_na(list(sex = sexo_em_falta)) ->
pinguins
n_femeas <- sum(pinguins$sex == "female")
n_machos <- nrow(pinguins) - n_femeas
solution <- n_femeas / n_machos
O valor pretendido é 1.036.
Use as seguintes linhas de código para ler o ficheiro de dados que deve usar nesta pergunta e em todas as seguintes.
url <- ‘https://web.tecnico.ulisboa.pt/paulo.soares/iadme/dados/penguins_alt_female.csv’
pinguins <- read.csv(url, stringsAsFactors = TRUE)
Nota: atenção às aspas!
De entre as variáveis numéricas, a que tem o maior valor do coeficiente de variação é:
if (medida == "coeficiente de variação") {
pinguins |>
summarise(across(where(is.numeric), \(x) sd(x) / mean(x))) ->
res
} else {
pinguins |>
summarise(across(where(is.numeric), mad)) ->
res
}
solution <- ifelse(extremo == "maior", which.max(res), which.min(res))
## bill_len bill_dep flipper_len body_mass year
## 1 0.124302 0.11514 0.0699883 0.190862 0.00040695
A variável é body_mass.
As cinco variáveis numéricas ordenadas por ordem crescente do coeficiente de correlação linear com a variável body_mass são:
pinguins |>
select(where(is.numeric)) ->
tmp
if(medida == "da covariância"){
medidas <- var(tmp)
} else {
medidas <- cor(tmp)
}
medidas[,"body_mass"] |>
sort(decreasing = (sentido == "decrescente")) ->
medidas
medidas |>
names() ->
solution
## bill_dep year bill_len flipper_len body_mass
## -0.4719156 0.0422094 0.5951098 0.8712018 1.0000000
A ordem é bill_dep, year, bill_len, flipper_len, body_mass.
Construa um único gráfico que permita analisar visualmente a associação das variáveis categóricas sex e species com a variável body_mass.
library(ggplot2)
theme_set(theme_light())
cores <- c("darkorange", "mediumorchid1", "cyan4")
ggplot(pinguins) +
geom_boxplot(aes(sex, body_mass, fill = species)) +
scale_fill_manual(values = cores)
Construa uma única figura com os gráficos de dispersão que permita analisar visualmente a associação de cada uma das variáveis numéricas (excetuando a variável year) com a variável body_mass. Em todos os gráficos, deve ainda ser possível distinguir as três espécies de pinguins.
library(ggplot2)
theme_set(theme_light())
cores <- c("darkorange", "mediumorchid1", "cyan4")
pinguins |>
select(where(is.numeric), -year, species) |>
tidyr::pivot_longer(-c(body_mass, species), names_to = "Covariável",
values_to = "Valor") |>
ggplot() +
geom_point(aes(Valor, body_mass, color = species), alpha = 0.6) +
scale_color_manual(values = cores) +
facet_wrap(~ Covariável, scales = "free_x") +
theme(legend.position = "top")
Para avaliar o uso das variáveis species e island como covariáveis num modelo de regressão linear múltipla para explicar a variação da variável resposta body_mass, foi construído o seguinte gráfico:
O gráfico permite afirmar:
Observa-se a existência de associação entre as variáveis uma vez que alguns valores de uma das variáveis determinam univocamente o valor da outra. No entanto, isso não acontece para todos os valores, ou seja, a associação não é perfeita. Nestas condições, ambas as variáveis podem ser incluídas no modelo. Caso a contribuição de uma delas seja reduzida na presença da outra, poderá então ser removida.
No gráfico da esquerda da figura abaixo representa-se a reta de regressão estimada do modelo de regressão simples flipper_len ~ bill_dep. À direita representam-se os resultados do ajustamento de outro modelo de regressão com as mesmas variáveis mas a que se juntou a covariável categórica species.
O modelo de regressão linear múltipla que foi considerado pode ser definido por várias fórmulas:
flipper_len ~ (bill_dep + species)^2
flipper_len ~ bill_dep * species - bill_dep:species
flipper_len ~ bill_dep * species
flipper_len ~ bill_dep + species
flipper_len ~ bill_dep + species + bill_dep:species
Uma vez que as retas ajustadas para cada nível da covariável species não são paralelas, o modelo considerado inclui a interação entre as duas covariáveis. Esse modelo pode ser definido pelas fórmulas equivalentes:
flipper_len ~ (bill_dep + species)^2flipper_len ~ bill_dep * speciesflipper_len ~ bill_dep + species + bill_dep:speciesOs gráficos seguintes sugerem que a variável year deverá ter pouca influência na variação da variável resposta body_mass.
Ajuste um modelo de regressão linear múltipla de 1ª ordem sem essa covariável (Modelo 1) e indique a estimativa da diferença da massa corporal média entre um pinguim macho da ilha Dream e um pinguim fêmea da ilha Biscoe com valores comuns nas restantes covariáveis.
# # Por exemplo:
# ilha <- "Dream"
modelo_1 <- lm(body_mass ~ . - year, data = pinguins)
summary(modelo_1)
##
## Call:
## lm(formula = body_mass ~ . - year, data = pinguins)
##
## Residuals:
## Min 1Q Median 3Q Max
## -782.2 -167.5 -8.2 183.7 922.3
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -1539.86 574.37 -2.68 0.00771 **
## speciesChinstrap -270.18 88.44 -3.06 0.00243 **
## speciesGentoo 984.50 136.71 7.20 4.0e-12 ***
## islandDream -18.35 58.65 -0.31 0.75452
## islandTorgersen -26.32 60.18 -0.44 0.66215
## bill_len 19.98 7.10 2.81 0.00518 **
## bill_dep 70.02 19.50 3.59 0.00038 ***
## flipper_len 15.86 2.93 5.42 1.2e-07 ***
## sexmale 381.16 47.47 8.03 1.7e-14 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 290 on 333 degrees of freedom
## Multiple R-squared: 0.872, Adjusted R-squared: 0.869
## F-statistic: 284 on 8 and 333 DF, p-value: <2e-16
solution <- coef(modelo_1)[["sexmale"]] + coef(modelo_1)[[paste0("island", ilha)]]
O valor pretendido é 362.803 g.
Ajuste um novo modelo (Modelo 2) removendo a variável island do Modelo 1. Compare os dois modelos recorrendo a um teste-F adequado e indique o valor observado da estatística de teste.
modelo_2 <- update(modelo_1, . ~ . - island)
anv <- anova(modelo_2, modelo_1)
anv
## Analysis of Variance Table
##
## Model 1: body_mass ~ species + bill_len + bill_dep + flipper_len + sex
## Model 2: body_mass ~ (species + island + bill_len + bill_dep + flipper_len +
## sex + year) - year
## Res.Df RSS Df Sum of Sq F Pr(>F)
## 1 335 28012161
## 2 333 27995432 2 16729 0.099 0.905
solution <- anv$F[2]
O valor pretendido é 0.099.
Considere um terceiro modelo (Modelo 3) adicionando um termo de interação entre as variáveis species e sex ao Modelo 2. Indique o valor da variação observada no coeficiente de determinação ajustado entre este último modelo e o Modelo 1 com 6 casas decimais.
modelo_3 <- update(modelo_2, . ~ . + species:sex)
summ_1 <- summary(modelo_1)
summ_3 <- summary(modelo_3)
summ_3
##
## Call:
## lm(formula = body_mass ~ species + bill_len + bill_dep + flipper_len +
## sex + species:sex, data = pinguins)
##
## Residuals:
## Min 1Q Median 3Q Max
## -766.0 -168.8 -7.6 167.8 867.9
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -1713.69 559.55 -3.06 0.00237 **
## speciesChinstrap -118.61 84.93 -1.40 0.16345
## speciesGentoo 961.29 126.07 7.63 2.6e-13 ***
## bill_len 22.35 6.85 3.26 0.00121 **
## bill_dep 73.53 18.75 3.92 0.00011 ***
## flipper_len 15.78 2.83 5.58 4.9e-08 ***
## sexmale 416.07 54.58 7.62 2.6e-13 ***
## speciesChinstrap:sexmale -356.75 82.40 -4.33 2.0e-05 ***
## speciesGentoo:sexmale 64.04 68.71 0.93 0.35199
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 279 on 333 degrees of freedom
## Multiple R-squared: 0.882, Adjusted R-squared: 0.879
## F-statistic: 310 on 8 and 333 DF, p-value: <2e-16
if(tipo == "ajustado") {
solution <- summ_3$adj.r.squared - summ_1$adj.r.squared
} else {
solution <- summ_3$r.squared - summ_1$r.squared
}
O valor pretendido é 0.009626.
Para avaliar o Modelo 3 começou-se por produzir os seguintes três gráficos dos resíduos.
Com base nestes gráficos é razoável afirmar que:
Em conjunto, os gráficos sugerem que:
Com base no Modelo 3 calcule um intervalo de predição a um nível \(\gamma = 0.93\) para o valor da massa corporal de um pinguim com as seguintes características:
## species island sex bill_len bill_dep flipper_len
## 1 Adelie Dream female 33.9 19.2 172.4
Indique o comprimento do intervalo obtido.
# # Por exemplo:
# gama <- 0.95
# novo_pinguim <- data.frame(species = "Chinstrap", island = "Dream",
# sex = "female", bill_len = 51.5, bill_dep = 18.8,
# flipper_len = 196.4)
tipo <- ifelse(tipo == "confiança", "confidence", "prediction")
intervalo <- predict(modelo_3, novo_pinguim, interval = tipo, level = gama)
intervalo
## fit lwr upr
## 1 3175.98 2654.23 3697.73
solution <- intervalo[3] - intervalo[2]
O valor pretendido é 1043.5034.
Comece por fixar a semente do gerador de números pseudo-aleatórios em 2015. De seguida, use a função sample para separar o conjunto de dados em dois subconjuntos: treino e teste. Este último conjunto deverá conter 20% das observações.
Use o conjunto de treino para ajustar um modelo de regressão logística para a variável resposta sex em função de todas as outras variáveis. Remova todas as covariáveis não significativas ao nível de significância de 0.05 e ajuste um novo modelo reduzido.
Compare os dois modelos recorrendo ao teste de razão de verosimilhanças apropriado e indique o valor-p obtido.
# # Por exemplo:
# semente <- 2000
set.seed(semente)
n <- nrow(pinguins)
teste.index <- sample(n, size = 0.2 * n)
teste <- pinguins[teste.index, ]
treino <- pinguins[-teste.index, ]
logmodelo <- glm(sex ~ ., family = "binomial", data = treino)
summary(logmodelo)
##
## Call:
## glm(formula = sex ~ ., family = "binomial", data = treino)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.78e+02 6.84e+02 -0.26 0.79449
## speciesChinstrap -7.43e+00 1.73e+00 -4.28 1.8e-05 ***
## speciesGentoo -1.02e+01 3.01e+00 -3.39 0.00071 ***
## islandDream -1.06e-01 8.54e-01 -0.12 0.90118
## islandTorgersen -1.62e+00 1.08e+00 -1.50 0.13327
## bill_len 5.92e-01 1.35e-01 4.37 1.2e-05 ***
## bill_dep 1.46e+00 3.69e-01 3.95 7.7e-05 ***
## flipper_len 6.90e-02 5.89e-02 1.17 0.24189
## body_mass 5.46e-03 1.17e-03 4.68 2.9e-06 ***
## year 4.78e-02 3.41e-01 0.14 0.88879
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 379.71 on 273 degrees of freedom
## Residual deviance: 108.24 on 264 degrees of freedom
## AIC: 128.2
##
## Number of Fisher Scoring iterations: 7
logmodelo_R <- update(logmodelo, . ~ . - year - island - flipper_len)
anv <- anova(logmodelo_R, logmodelo, test = "LRT")
anv
## Analysis of Deviance Table
##
## Model 1: sex ~ species + bill_len + bill_dep + body_mass
## Model 2: sex ~ species + island + bill_len + bill_dep + flipper_len +
## body_mass + year
## Resid. Df Resid. Dev Df Deviance Pr(>Chi)
## 1 268 112.3
## 2 264 108.2 4 4.086 0.395
solution <- anv$`Pr(>Chi)`[2]
O valor pretendido é 0.395.
Recorra ao modelo reduzido anterior para predizer os valores da variável sex das observações no conjunto de teste. Use o valor de corte 0.5 para classificar cada pinguim de acordo com a probabilidade estimada.
Indique a proporção de pinguins macho corretamente classificados.
teste$pred_sex <- (predict(logmodelo_R, teste, type = "response") > 0.5)
teste$pred_sex <- as.factor(teste$pred_sex)
levels(teste$pred_sex) <- c("female", "male")
tab <- with(teste, table(sex, pred_sex))
prop <- diag(prop.table(tab, margin = 1))
prop
## female male
## 0.941176 0.852941
solution <- ifelse(sexo == "fêmea", prop[1], prop[2])
O valor pretendido é 0.8529.