IAT: 0.15, 0.35, and 0.65 are considered small, medium, and large levels of bias for individual scores. Positive means bias towards arts / against Math.
Os dados usados aqui vêm de uma replicação, conduzida em cerca de 30 laboratórios ao redor do mundo, do estudo de Nosek, Banaji & Greenwald (2002), “Sex differences in implicit math attitudes”. Os dados tratados foram disponibilizados por Robert J. Calin-Jageman para o workshop Teaching the New Statistics (osf.io/wx7ck), a partir dos dados originais da replicação (osf.io/pqf9r).
iat = read_csv(here::here(params$arquivo_dados), col_types = "dccdc")
iat = iat %>%
mutate(sex = factor(sex, levels = c("m", "f"), ordered = TRUE))
glimpse(iat)
## Rows: 165
## Columns: 5
## $ session_id <dbl> 2435230, 2435236, 2435237, 2435239, 2435240, 2435243, 2435…
## $ referrer <chr> "swpson", "swpson", "swpson", "swpson", "swpson", "swpson"…
## $ sex <ord> f, f, m, f, f, f, f, f, f, f, f, f, f, m, f, f, f, f, f, f…
## $ d_art <dbl> 0.39171550, 1.00715226, 0.26248436, 0.64749897, 0.58174417…
## $ iat_exclude <chr> "Include", "Include", "Include", "Include", "Include", "In…
iat %>%
ggplot(aes(x = d_art, fill = sex, color = sex)) +
geom_histogram(binwidth = .2, alpha = .4) +
geom_rug() +
facet_grid(sex ~ ., scales = "free_y") +
theme(legend.position = "None")
iat %>%
ggplot(aes(x = sex, y = d_art)) +
geom_quasirandom(width = .1)
iat %>%
ggplot(aes(x = sex, y = d_art)) +
geom_quasirandom(width = .1) +
stat_summary(geom = "point", fun.y = "mean", color = "red", size = 5)
## Warning: The `fun.y` argument of `stat_summary()` is deprecated as of ggplot2 3.3.0.
## ℹ Please use the `fun` argument instead.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
iat %>%
group_by(sex) %>%
summarise(media = mean(d_art), dp = sd(d_art), n = n())
## # A tibble: 2 × 4
## sex media dp n
## <ord> <dbl> <dbl> <int>
## 1 m 0.238 0.515 53
## 2 f 0.508 0.433 112
agrupado = iat %>%
group_by(sex) %>%
summarise(media = mean(d_art))
m = agrupado %>% filter(sex == "m") %>% pull(media)
f = agrupado %>% filter(sex == "f") %>% pull(media)
m - f
## [1] -0.2696448
library(boot)
theta <- function(d, i) {
agrupado = d %>%
slice(i) %>%
group_by(sex) %>%
summarise(media = mean(d_art))
m = agrupado %>% filter(sex == "m") %>% pull(media)
f = agrupado %>% filter(sex == "f") %>% pull(media)
m - f
}
set.seed(1234)
booted <- boot(data = iat,
statistic = theta,
R = 5000)
ci = tidy(booted,
conf.level = .95,
conf.method = "bca",
conf.int = TRUE)
glimpse(ci)
## Rows: 1
## Columns: 5
## $ statistic <dbl> -0.2696448
## $ bias <dbl> 0.0005327326
## $ std.error <dbl> 0.08168239
## $ conf.low <dbl> -0.4322362
## $ conf.high <dbl> -0.1135285
ci %>%
ggplot(aes(
x = "",
y = statistic,
ymin = conf.low,
ymax = conf.high
)) +
geom_pointrange() +
geom_point(size = 3) +
labs(x = "Diferença",
y = "IAT homens - mulheres")
p1 = iat %>%
ggplot(aes(x = sex, y = d_art)) +
geom_quasirandom(width = .1) +
stat_summary(geom = "point", fun.y = "mean", color = "red", size = 5)
p2 = ci %>%
ggplot(aes(
x = "",
y = statistic,
ymin = conf.low,
ymax = conf.high
)) +
geom_pointrange() +
geom_point(size = 3) +
ylim(-1, 1) +
labs(x = "Diferença",
y = "IAT homens - mulheres")
grid.arrange(p1, p2, ncol = 2)
Em média, as mulheres que participaram do experimento tiveram uma associação implícita (medida pelo IAT) com a matemárica positiva e média (bem próxima do limiar com forte) (média 0.508, desv. padrão 0.433, N = 112). Homens tiveram uma associação positiva com a matemática, portanto menor que a das mulheres (média 0.238, desv. padrão 0.515, N = 53). Houve portanto uma diferença considerável entre homens e mulheres (diferença das médias -0.270, 95% CI [-0.432, -0.114]). A partir desta amostra, estimamos que a diferença real na população provavelmente está entre 0.11 e 0.43 ponto na escala IAT, faixa que cruza o limiar considerado pequeno (0.15) e chega perto do limiar médio (0.35), o suficiente para diferenciar uma diferença pequena de uma moderada, mas não para confirmar uma diferença grande.
Exemplos de possíveis conclusões para completar
Realize a análise e compare as conclusões obtidas nos dois casos experimentados:
Antes de reamostrar, verificamos se o critério de exclusão do estudo original marcou algum caso como inválido.
count(iat, iat_exclude)
## # A tibble: 1 × 2
## iat_exclude n
## <chr> <int>
## 1 Include 165
Todos os 165 casos estão marcados como "Include".
Filtramos explicitamente por esse valor para que o código permaneça
correto caso a base mude:
iat = iat %>%
filter(iat_exclude == "Include")
nrow(iat)
## [1] 165
Implementamos o próprio algoritmo de reamostragem, sem usar
boot(): cada reamostra seleciona 165 observações com
reposição (mesmo tamanho da amostra original), recalcula a diferença de
médias e armazena o resultado.
bootstrap_manual <- function(dados, n_boot = 5000, seed = 1234) {
set.seed(seed)
n <- nrow(dados)
map_dfr(1:n_boot, function(i) {
amostra <- dados %>% slice_sample(n = n, replace = TRUE)
medias <- amostra %>%
group_by(sex) %>%
summarise(media = mean(d_art), .groups = "drop")
m <- medias %>% filter(sex == "m") %>% pull(media)
f <- medias %>% filter(sex == "f") %>% pull(media)
tibble(media_m = m, media_f = f, diferenca = m - f)
})
}
boot_manual <- bootstrap_manual(iat)
boot_manual %>%
ggplot(aes(x = diferenca)) +
geom_histogram(bins = 40, fill = "steelblue", alpha = .7) +
geom_vline(xintercept = mean(boot_manual$diferenca), color = "red") +
geom_vline(xintercept = m - f, color = "darkgreen", linetype = "dashed") +
labs(
title = "Distribuição bootstrap da diferença (m - f)",
subtitle = "linha vermelha: média do bootstrap | linha verde: estimativa na amostra original",
x = "diferença de médias (bootstrap)",
y = "contagem"
)
A distribuição acima é aproximadamente simétrica, com uma média do bootstrap (-0.2692) muito próxima da estimativa na amostra original (-0.2696), ligeiramente menos negativa. Essa pequena discrepância é justamente o viés que os diferentes métodos de IC tratam de formas diferentes, o que motiva comparar mais de um método em vez de usar só um.
A partir dessa mesma distribuição bootstrap, calculamos os intervalos por dois métodos distintos:
O método mais direto: os limites do IC são os percentis 2.5% e 97.5% da própria distribuição bootstrap. Assume que a distribuição bootstrap já aproxima bem a distribuição amostral da estatística, sem correções adicionais.
ic_percentil <- boot_manual %>%
summarise(
estimate = mean(diferenca),
conf.low = quantile(diferenca, .025),
conf.high = quantile(diferenca, .975)
)
ic_percentil
## # A tibble: 1 × 3
## estimate conf.low conf.high
## <dbl> <dbl> <dbl>
## 1 -0.269 -0.427 -0.112
Diferente do percentil, o método Basic não usa os percentis da
distribuição bootstrap diretamente como limites do IC. Em vez disso,
reflete esses percentis em torno da estimativa observada na amostra
original (-0.2696), com a lógica de que o desvio entre a reamostra e a
estimativa original (d* = θ* − θ̂) é o que deveria ser usado
para construir o intervalo, não o valor absoluto de θ*:
\[IC_{basic} = \left[\,2\hat\theta - q_{0.975},\;\; 2\hat\theta - q_{0.025}\,\right]\]
onde q_{0.025} e q_{0.975} são os mesmos
percentis da distribuição bootstrap usados no método Percentil.
theta_hat <- m - f
ic_basic <- tibble(
estimate = theta_hat,
conf.low = 2 * theta_hat - quantile(boot_manual$diferenca, .975),
conf.high = 2 * theta_hat - quantile(boot_manual$diferenca, .025)
)
ic_basic
## # A tibble: 1 × 3
## estimate conf.low conf.high
## <dbl> <dbl> <dbl>
## 1 -0.270 -0.428 -0.112
comparacao <- bind_rows(
ci %>%
transmute(metodo = "Biblioteca (BCa)",
estimate = statistic, conf.low, conf.high),
ic_percentil %>% mutate(metodo = "Manual (Percentil)"),
ic_basic %>% mutate(metodo = "Manual (Basic)")
) %>%
select(metodo, estimate, conf.low, conf.high) %>%
mutate(largura_ic = conf.high - conf.low)
comparacao
## # A tibble: 3 × 5
## metodo estimate conf.low conf.high largura_ic
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 Biblioteca (BCa) -0.270 -0.432 -0.114 0.319
## 2 Manual (Percentil) -0.269 -0.427 -0.112 0.316
## 3 Manual (Basic) -0.270 -0.428 -0.112 0.316
comparacao %>%
ggplot(aes(x = metodo, y = estimate, ymin = conf.low, ymax = conf.high)) +
geom_pointrange(size = 1) +
geom_hline(yintercept = 0, linetype = "dashed", color = "grey40") +
coord_flip() +
labs(
title = "IC 95% para a diferença (homens - mulheres): três métodos",
x = NULL,
y = "diferença de médias no IAT"
)
Discussão da comparação
Com os dados reais (BCa: -0.270, IC [-0.432, -0.114]; Percentil: -0.269, IC [-0.427, -0.112]; Basic: -0.270, IC [-0.428, -0.112]), os três métodos concordam na direção (todos negativos, nenhum cruza o zero) e têm larguras de intervalo muito próximas (0.319 para o BCa contra 0.316 para os dois métodos manuais), porque o tamanho amostral (N = 165) já é grande o suficiente para que o viés e a assimetria da distribuição bootstrap sejam modestos.
A diferença que existe entre eles não é de largura, e sim de posicionamento: o método Basic desloca o intervalo em relação ao Percentil na direção oposta ao viés observado na distribuição bootstrap. Como a média do bootstrap ficou ligeiramente menos negativa do que a estimativa da amostra original, o método Basic corrige isso deslocando o intervalo para valores um pouco mais negativos, enquanto o Percentil aceita os percentis da distribuição bootstrap sem essa correção. O BCa da biblioteca faz uma correção semelhante à do Basic, mas soma a ela uma correção adicional de assimetria (o parâmetro de aceleração, estimado por jackknife), o que explica por que o intervalo do BCa é um pouco mais largo que o do Basic, mesmo corrigindo o mesmo tipo de viés.
Dado que a distribuição bootstrap desta amostra mostra apenas uma assimetria leve, os três métodos convergem para conclusões práticas equivalentes aqui. Isso não seria necessariamente verdade em uma amostra menor ou com uma distribuição mais assimétrica, onde a escolha do método poderia mudar a conclusão sobre se o IC cruza ou não um limiar relevante (por exemplo, o zero, ou os limiares de efeito pequeno/médio/grande do IAT). Diante disso, o BCa é o método que inspira mais confiança para generalizar esta estimativa, por corrigir tanto o viés quanto a assimetria observados; os métodos Percentil e Basic servem aqui como verificação de robustez, e o fato de os três concordarem é evidência de que a conclusão não depende de detalhes de implementação.