Nos quadros Sua vez, você ajusta um modelo e passa para checar um número extraído dele — um valor-p, coeficientes, um intervalo. Todos usam as lagoas com dossel medido, como este capítulo. Comece cada sessão com:
Two sample t-test (unequal variance)
------------------------------------
Population details:
parameter of interest: Mean difference
value under h_0: 0
point estimate: 1.01849
95% confidence interval: (-0.452, 2.489)
Test summary:
outcome with 95% confidence: fail to reject h_0
two-sided p-value: 0.1734
Details:
number of observations: [95,78]
t-statistic: 1.3673234271337709
degrees of freedom: 168.03764735213443
empirical standard error: 0.7448775533304762
Em R
t.test(richness ~ hydro, data = ponds) usa Welch por padrão — o mesmo que UnequalVarianceTTest. Para o teste de variâncias iguais, use EqualVarianceTTest.
NotaSua vez 8.1 — O hidroperíodo afeta o tamanho corporal?
Compare body_size entre lagoas permanentes e temporárias com um teste t de Welch. Passe o valor-p para checar("8.1", ...).
DicaDica
Reaproveite perm e temp_ do bloco acima. pvalue(teste) extrai o valor-p.
p ≈ 0,10: nenhuma evidência de diferença. Aqui podemos ir além do usual, porque na simulação o hidroperíodo realmente não afeta o tamanho corporal. Com dados reais, um teste não significativo não mostra que o efeito não existe — só que os dados não permitem dizer.
O processo gerador (ver scripts/make_data.jl) usou \(38.0 + 0.9\,(\text{temp} - 24.5) - 0.04\,\text{canopy}\). Compare com as estimativas: essa é a vantagem de ensinar com dados simulados.
Ajuste body_size ~ temp_c + canopy + hydro e calcule o intervalo de confiança de 95% para o coeficiente de temp_c. Ele contém o valor verdadeiro, 0,9? Passe o intervalo (dois números) para checar("8.3", ...).
DicaDica
confint(m) retorna uma linha por coeficiente; temp_c é a segunda, então confint(m)[2, :].
Julia trata String e CategoricalArray como fatores automaticamente, com codificação de tratamento (dummy) e o primeiro nível como referência — igual ao R. Para mudar a referência ou o esquema de contrastes:
O nível de referência não tem coeficiente próprio: ele fica absorvido no intercepto, e as outras regiões são comparadas com ele. Sem contrasts, a referência é o primeiro nível em ordem alfabética, Amazon.
modelos = ["temp"=> m1,"temp+canopy"=> m2,"temp+can+reg"=> m3,"temp*hydro"=> m4]DataFrame( modelo =first.(modelos), k = [length(coef(m)) for (_, m) in modelos], aic =round.([aic(m) for (_, m) in modelos], digits =1), bic =round.([bic(m) for (_, m) in modelos], digits =1), adj_r2 =round.([adjr2(m) for (_, m) in modelos], digits =3),)
4×5 DataFrame
Row
modelo
k
aic
bic
adj_r2
String
Int64
Float64
Float64
Float64
1
temp
2
801.4
810.9
0.542
2
temp+canopy
3
775.6
788.2
0.607
3
temp+can+reg
5
776.1
795.0
0.611
4
temp*hydro
4
803.5
819.3
0.541
# teste F entre modelos aninhados, equivalente a anova() no Rftest(m1.model, m2.model, m3.model)
res =residuals(m3)fit_ =predict(m3)fig =Figure(size = (860, 350))ax1 =Axis(fig[1, 1], xlabel ="Valores ajustados", ylabel ="Resíduos", title ="(a) Resíduos vs ajustados")scatter!(ax1, fit_, res, color = (:steelblue, 0.6))hlines!(ax1, 0, color =:grey40, linestyle =:dash)ax2 =Axis(fig[1, 2], xlabel ="Quantis teóricos", ylabel ="Quantis amostrais", title ="(b) QQ-plot")# NOTA: Makie exporta `qqnorm` como recipe de gráfico, então os quantis são# calculados explicitamente aqui em vez de virem de uma função auxiliar.n =length(res)teoricos =quantile.(Normal(0, 1), ((1:n) .-0.5) ./ n)scatter!(ax2, teoricos, sort(res), color = (:darkorange, 0.6))ablines!(ax2, 0, std(res), color =:grey40, linestyle =:dash)ax3 =Axis(fig[1, 3], xlabel ="Resíduos", ylabel ="Frequência", title ="(c) Distribuição")hist!(ax3, res, bins =20, color = (:seagreen, 0.7))fig
Figura 8.1: Diagnóstico de resíduos do modelo m3.
AvisoUma lacuna real
R tem plot(modelo), que devolve os quatro gráficos de diagnóstico de uma vez, e performance::check_model(), que vai muito além. Julia não tem equivalente consolidado; os diagnósticos acima são montados à mão. É uma lacuna genuína, e o tipo de coisa que um pacote da comunidade resolveria bem.
NotaSua vez 8.5 — Quantos resíduos grandes?
Se os resíduos de m3 forem aproximadamente normais, cerca de 5% deles devem estar a mais de dois desvios-padrão de zero. Calcule a proporção que está e passe-a para checar("8.5", ...).
DicaDica
Divida res (do bloco de diagnóstico) por std(res) e tire a média de abs.(z) .> 2 — a média de valores true/false é uma proporção.
CuidadoSolução
z = res ./std(res)prop_grandes =mean(abs.(z) .>2)
0.057803468208092484
checar("8.5", prop_grandes)
✓ Correto!
Cerca de 5,8% — 10 de 173 resíduos, perto dos 5% esperados. É a versão numérica do QQ-plot acima.
8.7 Modelos mistos
MixedModels.jl(Bates et al. 2026) é mantido por Douglas Bates, primeiro autor do lme4(Bates et al. 2015), e usa a mesma notação de fórmula — inclusive (1 | grupo).
Sobre desempenho: comparações entre os dois dependem fortemente do modelo, do tamanho dos dados e da estrutura dos efeitos aleatórios, e não conheço um benchmark publicado que eu possa citar aqui. Se o tempo de ajuste importa para o seu problema, meça no seu próprio caso.
Idêntico, inclusive a notação (1 | grupo). MixedModels.jl também suporta (1 + x | grupo), (1 | a) + (1 | b) e termos aninhados.
NotaSua vez 8.6 — Um intercepto aleatório para região
Ajuste um modelo misto de body_size em temp_c com intercepto aleatório para region e passe os efeitos fixos para checar("8.6", ...). Depois olhe o VarCorr do seu modelo: quanto da variação a região explica?
DicaDica
Mesma estrutura de mm1, com uma fórmula menor. fixef(mm) retorna os efeitos fixos.
A variância de região é estimada como exatamente zero — um ajuste singular. A simulação não tem efeito de região sobre o tamanho corporal, e três regiões trazem muito pouca informação sobre uma variância de qualquer forma. Com variância zero, o modelo misto se reduz a lm(@formula(body_size ~ temp_c), ponds): compare os coeficientes.
# intervalos por bootstrap paramétrico — rápido o bastante para ser rotinausingRandomboot =parametricbootstrap(MersenneTwister(42), 1000, mm1)DataFrame(shortestcovint(boot))
Desafios
Ajuste body_size ~ canopy separadamente para cada região e compare as inclinações com as de um único modelo com interação canopy * region. Por que elas coincidem?
O modelo m4 tem interação significativa? A simulação não tem interação temp_c × hydro: se a sua fosse significativa, o que isso significaria?
No 8.6 a variância de região saiu zero. Compare mm1 com um modelo que trata region como efeito fixo. Com três regiões, qual você reportaria, e por quê?
Bates, Douglas, Phillip Alday, Dave Kleinschmidt, et al. 2026. MixedModels.jl: A Julia package for fitting (statistical) mixed-effects models. Versão 5.8.2. Released. https://github.com/JuliaStats/MixedModels.jl.
Bates, Douglas, Martin Mächler, Ben Bolker, e Steve Walker. 2015. «Fitting Linear Mixed-Effects Models Using lme4». Journal of Statistical Software 67 (1): 1–48. https://doi.org/10.18637/jss.v067.i01.