Sobre IAT

IAT: 0.15, 0.35, and 0.65 are considered small, medium, and large level 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”: como possível explicação para a menor participação de mulheres em ciência e matemática, os autores encontraram atitudes implícitas mais negativas em relação à matemática (frente às artes) em mulheres do que em homens, medidas por IAT. A replicação usada aqui simplificou o desenho original para um único IAT. 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).

Análise de uma replicação

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)) +
    geom_histogram(binwidth = .2, alpha = .5, color = "black") +
    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.

Qual a diferença na amostra
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

Parte 1

Conclusão

Considerando os dados de swpson, 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), ficando entre pequena e média, mais próxima da pequena. Houve portanto uma diferença moderada entre homens e mulheres (diferença das médias = 0.270).


Exemplos de possíveis conclusões para completar

  • mulheres têm uma associação negativa consideravelmente mais forte, com uma diferença dee 0.7 na escala IAT, o suficiente para diferenciar uma associação neutra de uma muito forte contra a matemática.
  • mulheres têm uma associação negativa mais forte, porém essa diferença é pequena, e não é relevante na prática.

Parte 2

Considerando as características dos dados, refazemos a análise acima com base em intervalos de confiança, usando duas abordagens de bootstrap (via pacote e implementada manualmente), para comparar se as conclusões coincidem.

Checando exclusões do estudo original

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" nesta amostra. Filtramos explicitamente por esse valor, mesmo sem efeito sobre N aqui, para que o código permaneça correto caso a base mude:

iat = iat %>%
    filter(iat_exclude == "Include")

nrow(iat)
## [1] 165

Abordagem 1: bootstrap via pacote {boot}

theta_grupos <- function(d, i) {
    d2 <- d %>% slice(i)

    medias <- d2 %>%
        group_by(sex) %>%
        summarise(media = mean(d_art), .groups = "drop")

    m <- medias %>% filter(sex == "m") %>% pull(media)
    f <- medias %>% filter(sex == "f") %>% pull(media)

    c(media_m = m, media_f = f, diferenca = m - f)
}

set.seed(123)
boot_lib <- boot(data = iat, statistic = theta_grupos, R = 5000)

ci_lib <- tidy(
    boot_lib,
    conf.level  = .95,
    conf.method = "bca",
    conf.int    = TRUE
)

ci_lib
## # A tibble: 3 × 6
##   term      statistic      bias std.error conf.low conf.high
##   <chr>         <dbl>     <dbl>     <dbl>    <dbl>     <dbl>
## 1 media_m       0.238 -0.00183     0.0708   0.0954     0.370
## 2 media_f       0.508  0.000882    0.0404   0.428      0.585
## 3 diferenca    -0.270 -0.00272     0.0810  -0.432     -0.115

Usamos BCa (bias-corrected and accelerated) por ser mais robusto a distribuições assimétricas e a viés na distribuição bootstrap do que o método percentil simples.

Abordagem 2: bootstrap implementado manualmente

bootstrap_manual <- function(dados, n_boot = 5000, seed = 123) {
    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)

Usamos o método percentil (percentis 2.5% e 97.5% da distribuição bootstrap) por ser o mais direto de implementar sem depender de nenhum pacote além do necessário para reamostrar e resumir dados. Com n = 165 e a distribuição bootstrap abaixo aproximadamente simétrica, percentil e BCa tendem a convergir para valores próximos.

boot_manual %>%
    ggplot(aes(x = diferenca)) +
    geom_histogram(bins = 40, fill = "steelblue", alpha = .7) +
    geom_vline(xintercept = mean(boot_manual$diferenca), color = "red") +
    labs(
        title = "Distribuição bootstrap da diferença (m - f)",
        x = "diferença de médias (bootstrap)",
        y = "contagem"
    )

resumir_ic_percentil <- function(x) {
    tibble(
        estimate = mean(x),
        conf.low  = quantile(x, .025),
        conf.high = quantile(x, .975)
    )
}

ci_manual <- bind_rows(
    media_m   = resumir_ic_percentil(boot_manual$media_m),
    media_f   = resumir_ic_percentil(boot_manual$media_f),
    diferenca = resumir_ic_percentil(boot_manual$diferenca),
    .id = "term"
)

ci_manual
## # A tibble: 3 × 4
##   term      estimate conf.low conf.high
##   <chr>        <dbl>    <dbl>     <dbl>
## 1 media_m      0.237   0.0976     0.375
## 2 media_f      0.509   0.428      0.588
## 3 diferenca   -0.272  -0.434     -0.110

Comparando as duas abordagens

comparacao <- bind_rows(
    ci_lib %>%
        select(term, estimate = statistic, conf.low, conf.high) %>%
        mutate(metodo = "boot::boot (BCa)"),
    ci_manual %>%
        mutate(metodo = "manual (percentil)")
) %>%
    mutate(largura_ic = conf.high - conf.low)

comparacao
## # A tibble: 6 × 6
##   term      estimate conf.low conf.high metodo             largura_ic
##   <chr>        <dbl>    <dbl>     <dbl> <chr>                   <dbl>
## 1 media_m      0.238   0.0954     0.370 boot::boot (BCa)        0.274
## 2 media_f      0.508   0.428      0.585 boot::boot (BCa)        0.158
## 3 diferenca   -0.270  -0.432     -0.115 boot::boot (BCa)        0.317
## 4 media_m      0.237   0.0976     0.375 manual (percentil)      0.277
## 5 media_f      0.509   0.428      0.588 manual (percentil)      0.160
## 6 diferenca   -0.272  -0.434     -0.110 manual (percentil)      0.324
comparacao %>%
    filter(term == "diferenca") %>%
    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): comparação entre métodos",
        x = NULL,
        y = "diferença de médias no IAT"
    )

As duas linhas acima ficaram visualmente sobrepostas, o que evidencia que a escolha do método de bootstrap não determina a conclusão: trata-se de um resultado robusto, e não de um artefato da implementação.

Magnitude do efeito frente às faixas de referência do IAT

faixas_iat = tibble(
    faixa = c("pequeno", "médio", "grande"),
    valor = c(.15, .35, .65)
)

comparacao %>%
    filter(metodo == "boot::boot (BCa)") %>%
    mutate(term = factor(term,
                          levels = c("diferenca", "media_f", "media_m"),
                          labels = c("diferença (m - f)", "média mulheres", "média homens")),
           term_num = as.numeric(term)) %>%
    ggplot(aes(x = term_num, y = estimate, ymin = conf.low, ymax = conf.high)) +
    geom_hline(yintercept = 0, color = "grey40") +
    geom_hline(data = faixas_iat, aes(yintercept = valor),
               linetype = "dashed", color = "orange") +
    geom_text(data = faixas_iat, aes(x = 3.4, y = valor, label = faixa),
              inherit.aes = FALSE, vjust = -.4, size = 3, color = "orange4") +
    geom_pointrange(size = 1) +
    scale_x_continuous(
        breaks = 1:3,
        labels = c("diferença (m - f)", "média mulheres", "média homens")
    ) +
    coord_flip(clip = "off") +
    labs(
        title = "Médias por grupo e diferença, com faixas de referência do IAT",
        subtitle = "linhas laranja = limiares pequeno (.15) / médio (.35) / grande (.65) de viés",
        x = NULL,
        y = "escore IAT (d_art)"
    ) +
    theme(plot.margin = margin(t = 20, r = 5, b = 5, l = 5))

Visualização de estimação (dados brutos + efeito)

p1 = iat %>%
    ggplot(aes(x = sex, y = d_art)) +
    geom_quasirandom(width = .1, alpha = .5) +
    stat_summary(geom = "point", fun = "mean", color = "red", size = 4) +
    labs(x = "sexo", y = "d_art (escore IAT)", title = "Dados brutos")

p2 = comparacao %>%
    filter(term == "diferenca", metodo == "boot::boot (BCa)") %>%
    ggplot(aes(x = "", y = estimate, ymin = conf.low, ymax = conf.high)) +
    geom_hline(yintercept = 0, linetype = "dashed", color = "grey40") +
    geom_pointrange(size = 1) +
    labs(
        x = NULL,
        y = "diferença (m - f)",
        title = "IC 95% da diferença"
    )

grid.arrange(p1, p2, ncol = 2)

Conclusão (Parte 2)

Considerando os dados de swpson (n = 165, sendo 53 homens e 112 mulheres), o bootstrap via {boot} (BCa) estimou uma diferença de médias (homens - mulheres) de -0.270, IC 95% [-0.432, -0.115]. O bootstrap implementado manualmente (percentil) chegou a uma estimativa de -0.272, IC 95% [-0.434, -0.110], resultado consistente com a primeira abordagem: os intervalos praticamente se sobrepõem por completo.

O intervalo não inclui o zero em nenhuma das duas abordagens, o que dá confiança razoável de que a direção do efeito é real nesta população: mulheres apresentam, em média, uma associação implícita mais forte contra a matemática (a favor das artes) do que homens, resultado consistente com o achado original de Nosek et al. (2002).

Em termos de magnitude: a média das mulheres (0.508) fica entre os limiares médio (0.35) e grande (0.65); a dos homens (0.238), entre pequeno (0.15) e médio (0.35). A diferença entre grupos (≈0.27) é, ela mesma, do tamanho de um efeito entre pequeno e médio. A largura do IC (≈0.32 ponto) mostra que a amostra permite afirmar a direção do efeito com confiança, mas deixa incerteza sobre sua magnitude exata dentro dessa faixa: o intervalo vai de perto do limiar pequeno (0.11) a perto do limiar médio (0.43).