Econometria Aplicada - Exercício 3

Autor

José Victor Santos Lopes

Data de Publicação

14 de setembro de 2025

0.1 Problema

Uma ONG com atuação na cidade do Rio de Janeiro ajuda escolas a implementarem programas de tutoria depois do horário da aula para ajudar alunos do Ensino Fundamental 1 a melhorarem seu desempenho em matemática. A ideia consiste em treinar alguns alunos do Ensino Fundamental 2 técnicas de ensino de aritmética básica, para que eles possam, fora do horário de aula, ajudar os alunos mais novos com a lição de casa e outras dúvidas de matemática.

A Secretaria do Estado de São Paulo observou os resultados preliminares desse programa e se animou para tentar implementar em larga escala no estado como um todo. Primeiro, no entanto, ela gostaria de fazer um experimento com as escolas da cidade de São Paulo para avaliar o impacto dessa iniciativa, antes de expandi-la como política pública para o estado como um todo.

Para isso, a Secretaria pretende usar os dados do SARESP, uma avaliação anual aplicada pela própria Secretaria com a finalidade de diagnosticar e acompanhar a evolução da educação básica paulista. Especificamente, a Secretaria irá utilizar os dados do SARESP de 2021 para alunos do 5º ano do Ensino Fundamental 1 na cidade de São Paulo.

0.2 Exploração Descritiva dos Dados

Nesta seção apresento um panorama geral da base após os filtros de validade e deduplicação: distribuição de variáveis numéricas e frequências de variáveis categóricas. Isso fornece contexto antes de partirmos para as simulações de poder.

# Pacotes
library(dplyr)
library(data.table)
library(tidyverse)
library(fixest)
library(ggplot2)
library(pwr)
library(stargazer)
library(kableExtra)

# Base
# Download único do RData (GitHub)
.download_rdata <- function(url) {
    tf <- tempfile(fileext = ".RData")
    httr::GET(url, httr::write_disk(tf, overwrite = TRUE))
    tf
}
DATA_URL_MAIN <- "https://github.com/josevictorsl/econometriaaplicadaeesp/raw/main/base_EA3.RData"

tf_rdata <- .download_rdata(DATA_URL_MAIN)
load(tf_rdata)

# Ajustes na base
df_5_sp <- df_5_sp %>%
    select(-NEC_ESP_5) %>%
    filter(validade == 1) %>%
    distinct(CD_ALUNO, .keep_all = T)

## Funções auxiliares para simulação de poder e MDE

simulate_power <- function(data, design = c("school","student"), outcome, effect_grid, N = 30, p_treat = 0.5, alpha = 0.05) {
    design <- match.arg(design)
    id_school <- "CODESC"
    id_student <- "CD_ALUNO"
    id_cluster <- ifelse(design == "school", id_school, id_student)

    # Modelos incrementais: lista de fórmulas (tratamento + controles cumulativos)
    form_list <- list(
        as.formula(paste(outcome, "~ treat")),
        as.formula(paste(outcome, "~ treat + porc_ACERT_lp")),
        as.formula(paste(outcome, "~ treat + porc_ACERT_lp + porc_ACERT_CIE")),
        as.formula(paste(outcome, "~ treat + porc_ACERT_lp + porc_ACERT_CIE + factor(TP_SEXO)"))
    )

    out <- lapply(effect_grid, function(ate){
        reps <- lapply(seq_len(N), function(r){
            if (design == "school") {
                assign_df <- data %>% distinct(.data[[id_school]]) %>% mutate(treat = rbinom(n(), 1, p_treat))
                sim_df <- data %>% left_join(assign_df, by = setNames(id_school, id_school))
            } else {
                assign_df <- data %>% distinct(.data[[id_student]]) %>% mutate(treat = rbinom(n(), 1, p_treat))
                sim_df <- data %>% left_join(assign_df, by = setNames(id_student, id_student))
            }
            sim_df <- sim_df %>% mutate(!!outcome := .data[[outcome]] + treat * ate)

            models <- lapply(form_list, function(fm){
                if (design == "school") {
                    feols(fm, data = sim_df, cluster = ~ CODESC, lean = TRUE)
                } else {
                    feols(fm, data = sim_df, se = "hetero", lean = TRUE)
                }
            })

            tibble(
                rep = r,
                model = paste0("Model", seq_along(models)),
                ate_true = ate,
                reject = vapply(models, function(m) pvalue(m)["treat"] < alpha, logical(1)),
                beta_hat = vapply(models, function(m) coef(m)["treat"], numeric(1))
            )
        })
        bind_rows(reps)
    })

    sim_all <- bind_rows(out)
    power_table <- sim_all %>%
        group_by(ate_true, model) %>%
        summarise(power = mean(reject), se_beta = sd(beta_hat), .groups = "drop") %>%
        mutate(design = design, outcome = outcome)
    list(raw = sim_all, summary = power_table)
}

compute_mde_curve <- function(power_summary, target_powers = c(0.7,0.8,0.9), alpha = 0.05){
    # Estimar SE do estimador em ate_true = 0 (por modelo)
    se_null <- power_summary %>% filter(ate_true == 0) %>% select(model, se_beta, design, outcome)
    # Converter para MDE usando aproximação normal/t; aqui usamos quantil z ~ qt para df grandes
    res <- lapply(target_powers, function(pw){
        kappa <- pw # poder desejado
        t_alpha <- qnorm(1 - alpha/2)
        # Para poder (1 - kappa) vs fórmula original: interpretamos kappa como (1 - beta). Ajustar naming:
        t_beta <- qnorm(pw) # quantil para poder
        se_null %>% mutate(power_target = pw, MDE = (t_alpha + t_beta) * se_beta)
    })
    bind_rows(res)
}

## Exploração de proporção tratada (p_treat) para efeito intermediário
explore_p_treat <- function(data, design, outcome, effect_grid, candidate_p = seq(0.3,0.7,0.1), target_effect = 0.25, N = 25, alpha = 0.05){
    # Seleciona o efeito na grade mais próximo do alvo
    eff_pick <- effect_grid[which.min(abs(effect_grid - target_effect))]
    results <- lapply(candidate_p, function(pv){
        sim <- simulate_power(data, design = design, outcome = outcome, effect_grid = c(0, eff_pick), N = N, p_treat = pv, alpha = alpha)
        # Poder para o efeito escolhido (exclui ate=0)
        pow_mid <- sim$summary %>% filter(ate_true == eff_pick) %>% mutate(p_treat = pv)
        pow_mid
    })
    res <- bind_rows(results)
    res %>% group_by(model) %>% mutate(rank_power = rank(-power, ties.method = "first")) %>% ungroup()
}

## RESUMO EXPLORATÓRIO FORMATADO

# Função para sumarizar variáveis numéricas
num_summary <- df_5_sp %>%
    select(where(is.numeric)) %>%
    pivot_longer(everything(), names_to = "variavel", values_to = "valor") %>%
    group_by(variavel) %>%
    summarise(
        n        = sum(!is.na(valor)),
        miss     = sum(is.na(valor)),
        media    = mean(valor, na.rm = TRUE),
        sd       = sd(valor, na.rm = TRUE),
        min      = min(valor, na.rm = TRUE),
        p25      = quantile(valor, 0.25, na.rm = TRUE),
        mediana  = median(valor, na.rm = TRUE),
        p75      = quantile(valor, 0.75, na.rm = TRUE),
        max      = max(valor, na.rm = TRUE)
    ) %>%
    ungroup() %>%
    mutate(across(where(is.numeric), ~ round(.x, 2)))

# Função para sumarizar variáveis categóricas
cat_vars <- df_5_sp %>% select(where(~ is.character(.) || is.factor(.)))

cat_summary <- if (ncol(cat_vars) > 0) {
    purrr::map_dfr(names(cat_vars), function(v) {
        vec <- cat_vars[[v]]
        tab <- sort(table(vec), decreasing = TRUE)
        top_n <- head(tab, 5)
        tibble(
            variavel = v,
            n        = sum(!is.na(vec)),
            miss     = sum(is.na(vec)),
            unicos   = length(unique(vec)),
            top5     = paste(paste0(names(top_n), " (", as.integer(top_n), ")"), collapse = ", ")
        )
    })
} else {
    tibble(variavel = character(), n = integer(), miss = integer(), unicos = integer(), top5 = character())
}

# Tabelas formatadas
num_summary %>%
    arrange(variavel) %>%
    kable(caption = "Resumo numérico das variáveis (n, miss, média, dispersão e quantis)") %>%
    kable_styling(full_width = FALSE, bootstrap_options = c("striped", "hover", "condensed"))
Resumo numérico das variáveis (n, miss, média, dispersão e quantis)
variavel n miss media sd min p25 mediana p75 max
CDREDE 41504 0 10230.18 80.52 10101.0 10205.0 10210.0 10316.0 10318.0
CD_ALUNO 41504 0 30935467.94 1631283.21 20414497.0 29737880.5 30765902.0 31811081.8 37949301.0
CLASSE 41504 0 251003445.41 690014.11 250010063.0 250449055.0 250924891.0 251433959.0 253989727.0
CODESC 41504 0 306079.52 407491.20 61.0 3448.0 38180.0 902901.0 926103.0
CODMUN 41504 0 100.00 0.00 100.0 100.0 100.0 100.0 100.0
TIPOCLASSE 41504 0 0.00 0.00 0.0 0.0 0.0 0.0 0.0
TOTAL_PONTO_CIE 41504 0 13.15 3.82 0.0 11.0 13.0 16.0 24.0
TOTAL_PONTO_LP 41504 0 15.73 5.71 0.0 11.0 17.0 21.0 24.0
TOTAL_PONTO_MAT 41504 0 14.90 5.41 0.0 11.0 16.0 19.0 24.0
Tem_Nec 41504 0 0.00 0.04 0.0 0.0 0.0 0.0 1.0
cad_prova_cie 41504 0 13.50 7.51 1.0 7.0 13.0 20.0 26.0
cad_prova_lp 41504 0 13.49 7.49 1.0 7.0 13.0 20.0 26.0
cad_prova_mat 41504 0 13.49 7.49 1.0 7.0 13.0 20.0 26.0
particip_cie 41504 0 1.00 0.00 1.0 1.0 1.0 1.0 1.0
particip_lp 41504 0 1.00 0.00 1.0 1.0 1.0 1.0 1.0
particip_mat 41504 0 1.00 0.00 1.0 1.0 1.0 1.0 1.0
porc_ACERT_CIE 41504 0 54.78 15.90 0.0 45.8 54.2 66.7 100.0
porc_ACERT_MAT 41504 0 62.09 22.56 0.0 45.8 66.7 79.2 100.0
porc_ACERT_lp 41504 0 65.53 23.81 0.0 45.8 70.8 87.5 100.0
profic_cie 41504 0 217.14 48.87 74.9 186.3 219.9 250.8 375.9
profic_lp 41504 0 198.27 49.43 74.3 162.4 198.2 232.4 314.1
profic_mat 41504 0 209.32 47.92 80.5 174.6 208.7 242.6 333.4
validade 41504 0 1.00 0.00 1.0 1.0 1.0 1.0 1.0
cat_summary %>%
    arrange(variavel) %>%
    kable(caption = "Resumo categórico (frequências e top 5 níveis)") %>%
    kable_styling(full_width = FALSE, bootstrap_options = c("striped", "hover", "condensed"))
Resumo categórico (frequências e top 5 níveis)
variavel n miss unicos top5
DE 41504 0 13 SUL 3 (4500), LESTE 1 (4061), SUL 1 (3914), SUL 2 (3869), NORTE 1 (3809)
DT_NASCIMENTO 41504 0 1170 2/21/2011 (151), 1/28/2011 (140), 3/14/2011 (138), 3/10/2011 (136), 7/13/2010 (135)
MUN 41504 0 1 SAO PAULO (41504)
NEC_ESP_1 41504 0 7 (41448), FISICA-OUTROS (21), BAIXA VISAO (14), SURDEZ LEVE OU MODERADA (13), FISICA-CADEIRANTE (5)
NEC_ESP_2 41504 0 1 (41504)
NEC_ESP_3 41504 0 1 (41504)
NEC_ESP_4 41504 0 1 (41504)
NOMEDEP 41504 0 1 ESTADUAL - SE (41504)
NomeDepBol 41504 0 1 Rede Estadual (41504)
PERIODO 41504 0 2 MANHÃ (25081), TARDE (16423)
RegiaoMetropolitana 41504 0 1 Região Metropolitana de São Paulo (41504)
SERIE_ANO 41504 0 1 5º Ano EF (41504)
TP_SEXO 41504 0 2 M (20977), F (20527)
TURMA 41504 0 13 A (11006), B (10537), C (8367), D (5832), E (3012)
Tip_PROVA 41504 0 2 C (41490), A (14)
classific_cie 41504 0 3 Suficiente (29072), Insuficiente (7927), Avançado (4505)
classific_lp 41504 0 3 Suficiente (27419), Insuficiente (7618), Avançado (6467)
classific_mat 41504 0 3 Suficiente (27239), Insuficiente (10476), Avançado (3789)
nivel_profic_cie 41504 0 4 Básico (14663), Adequado (14409), Abaixo do Básico (7927), Avançado (4505)
nivel_profic_lp 41504 0 4 Básico (13716), Adequado (13703), Abaixo do Básico (7618), Avançado (6467)
nivel_profic_mat 41504 0 4 Básico (15525), Adequado (11714), Abaixo do Básico (10476), Avançado (3789)

1 Questão 1

Enunciado: Considere dois possíveis desenhos para o experimento: uma aleatorização no nível do aluno, outra no nível da escola. Assuma que a restrição orçamentária da Secretaria para o experimento permite qualquer divisão entre escolas tratadas e controle, e que ela irá escolher a proporção de tratados de forma a maximizar o poder do experimento. Para cada uma dessas formas de aleatorização, calcule através de simulações qual seria o MDE (Minimum Detectable Effect) do programa de tutoria na nota de matemática e na porcentagem de acerto dos estudantes em matemática, considerando diferentes níveis de poder. Apresente um gráfico do MDE versus diferentes níveis de poder. Comente os resultados obtidos.

Para definir o menor efeito de tratamento que conseguimos detectar com probabilidade pré‑especificada (MDE), partimos da Equação 1, que relaciona quantis da distribuição t (associados ao nível de significância e ao poder desejado) ao erro padrão do estimador de interesse (Cohen (1988); Hayes e Moulton (2017)). Ao longo da análise, fixamos o nível de significância em α = 5% e consideramos uma grade discreta de valores plausíveis para o ATE. Para cada ponto dessa grade calculamos, via simulação, a fração de vezes em que rejeitamos a hipótese nula de ausência de efeito: essa fração é a potência empírica do teste naquele valor de ATE.

\[ MDE = (t_{1-\kappa} + t_{\alpha})\, SE(\hat{\beta}) \tag{1}\]

O procedimento consiste em replicar aleatorizações (conforme o nível de cluster definido) e, em cada repetição, estimar modelos incrementais com diferentes conjuntos de controles. Comparando as taxas de rejeição ao longo da grade de efeitos, obtemos a função de poder. Posteriormente, invertemos essa relação para mapear níveis de poder em valores mínimos detectáveis.

1.1 Aleatorização por Escolas

Iniciamos com o desenho em que a unidade de randomização é a escola. Os resultados agregados de potência para cada valor de ATE e especificação de modelo encontram-se na Tabela 1.

A partir da Tabela 1 observamos como a inclusão sequencial de variáveis de controle (participação em outras áreas, desempenho em linguagens e ciências, e sexo) afeta o ganho de poder. A variável dependente em todas as colunas é a porcentagem de acertos em matemática (SARESP). Como esperado, o poder cresce à medida que o ATE hipotético aumenta. A trajetória dessa potência ao longo da grade de efeitos é visualizada na Figura 1.

Por fim, mantendo α = 5%, utilizamos os poderes simulados para derivar os MDE correspondentes, apresentados na Tabela 2.

Aspectos metodológicos (erros-padrão): no desenho em nível de escola, a inferência deve refletir a correlação intra‑cluster. Utilizam-se erros-padrão clusterizados por escola (cluster = ~ CODESC) em todas as simulações, obtendo estimativas de poder e MDE consistentes com a estrutura de dependência dos dados.

1.1.1 Comentários Analíticos

Os resultados abrangem os quatro pares Desenho×Desfecho: (Escola, porcentagem de acertos), (Escola, proficiência), (Aluno, porcentagem de acertos) e (Aluno, proficiência). Duas regularidades emergem:

  1. Desenho individual tende a produzir menores MDE para o mesmo poder alvo, refletindo maior número de unidades efetivas (ausente a penalização do ICC ao nível de escola).
  2. Entre desfechos, a proficiência apresenta, neste conjunto de dados, maior variabilidade relativa que a porcentagem de acertos; consequentemente, em algumas especificações o MDE é mais elevado para proficiência quando comparado à métrica de porcentagem (ver Tabela 3).

A exploração de proporções tratadas (p_treat) em Tabela 5 e Figura 4 sugere que, dentro do intervalo 0.3–0.7, a potência não é monotônica: em vários casos p≈0.5 maximiza ou está muito próximo do máximo de poder para um efeito intermediário (ATE ≈ 0.25). Pequenos desvios para 0.4 ou 0.6 não alteram substancialmente o poder, indicando uma superfície relativamente plana em torno do balanceamento. Isso reforça a escolha operacional simples de randomização 1:1, salvo restrições de custo diferencial por tratado.

As curvas de MDE vs poder ( Figura 2 ) mostram a esperada convexidade: ganhos iniciais de reduzir o MDE ao aumentar o poder de 0.7 para 0.8 são maiores do que de 0.8 para 0.9, implicando retornos marginais decrescentes em termos de exigência de tamanho de efeito detectável. Em termos de modelos, a inclusão progressiva de controles (Model1 → Model4) reduz o erro padrão e, portanto, desloca as curvas para baixo; porém, o ganho marginal entre Model3 e Model4 é menor do que entre Model1 e Model2, sugerindo que parte substancial da variância residual já é absorvida pelos primeiros controles acadêmicos.

Síntese: se o objetivo primário fosse eficiência estatística pura, a aleatorização em nível de aluno com especificação mais rica (Model4) minimizaria o MDE. Contudo, ao ponderar possíveis spillovers (discutidos na Questão 2), parte dessa vantagem pode ser ilusória caso a SUTVA seja violada. Assim, os números aqui servem de limite inferior potencial para o MDE alcançável em um cenário sem contaminação. Em termos de robustez (N=100), o erro Monte Carlo para uma estimativa de poder p é sqrt(p(1-p)/N); para p=0.80 ≈ 0.04; p=0.50 ≈ 0.05; p=0.90 ≈ 0.03. As diferenças relevantes entre modelos e desenhos superam essas margens, sustentando as conclusões qualitativas.

# Configuração de Simulação
set.seed(20092004)

## ALEATORIZAÇÃO POR ESCOLA ##

effect_grid <- seq(0, 0.5, 0.05)
alpha <- 0.05
MC_REPS <- 100

mdeE <- lapply(effect_grid, function(x) {
    sim <- lapply(seq_len(MC_REPS), function(i) {
        escolas <- tibble("CODESC" = df_5_sp$CODESC %>%
            unique()) %>%
            mutate(treat = rbinom(
                n = length(table(df_5_sp$CODESC %>%
                    unique())),
                size = 1,
                prob = 0.5
            )) %>%
            left_join(df_5_sp,
                by = "CODESC",
                multiple = "all"
            ) %>%
            mutate(y = porc_ACERT_MAT + treat * x)

        model <- feols(y ~ treat + csw0(porc_ACERT_lp, porc_ACERT_CIE, factor(TP_SEXO)),
                        data = escolas,
                        cluster = ~ CODESC,
                        lean = TRUE)

        tab <- tibble(
            "rep" = i,
            "reject" = sapply(model, function(x) pvalue(x)["treat"] < alpha),
            "model" = c("Model1", "Model2", "Model3", "Model4")
        )
    })
    sim <- setDT(do.call(bind_rows, sim))
    power_table <- tibble(
        "ATE" = x,
        "Model" = unique(sim$model),
        "power" = sapply(unique(sim$model), function(x) nrow(sim[model == x][reject == "TRUE"]) / MC_REPS)
    )
    power_table <- power_table %>% pivot_wider(names_from = "Model", values_from = "power")
    power_table
})
mdeE <- do.call(bind_rows, mdeE)
mdeE1 <- mdeE %>% pivot_longer(cols = starts_with("Model"), names_to = "Model", values_to = "Power")

# Mapeamento de rótulos de modelo para exibição em português
model_map <- setNames(paste("Modelo", 1:4), paste0("Model", 1:4))
mdeE1 <- mdeE1 %>% mutate(Model = factor(model_map[Model], levels = paste("Modelo",1:4)))

## Simulação (Escola -> proficiência)
effect_grid <- seq(0, 0.5, 0.05)
power_school_profic <- simulate_power(df_5_sp, design = "school", outcome = "profic_mat", effect_grid = effect_grid, N = MC_REPS, p_treat = 0.5)
school_profic_summary <- power_school_profic$summary

## Curvas MDE para Escola -> proficiência
mde_school_profic <- compute_mde_curve(school_profic_summary)
# Versão apenas para exibição com rótulos em português
mdeE_display <- mdeE %>%
    rename(`Modelo 1` = Model1, `Modelo 2` = Model2, `Modelo 3` = Model3, `Modelo 4` = Model4)
knitr::kable(mdeE_display)
Tabela 1: Power por ATE e Modelo (Aleatorização por Escola)
ATE Modelo 1 Modelo 2 Modelo 3 Modelo 4
0.00 0.02 0.04 0.04 0.04
0.05 0.09 0.09 0.10 0.10
0.10 0.02 0.07 0.08 0.08
0.15 0.02 0.10 0.09 0.09
0.20 0.06 0.12 0.12 0.12
0.25 0.08 0.14 0.14 0.14
0.30 0.12 0.27 0.24 0.26
0.35 0.08 0.23 0.27 0.28
0.40 0.08 0.23 0.30 0.32
0.45 0.05 0.31 0.38 0.38
0.50 0.12 0.45 0.48 0.51
ggplot(data = mdeE1, aes(x = ATE, y = Power, group = Model)) +
    geom_line(aes(color = Model)) +
    geom_point(aes(color = Model, shape = Model)) +
    theme_bw() +
    scale_y_continuous(n.breaks = 10) +
    scale_color_brewer(palette = "Dark2", direction = -1) +
    labs(
        x = "ATE",
        y = "Poder"
    )

mde_table <- mdeE %>%
    filter(ATE > 0)

sample_n <- length(unique(df_5_sp$CD_ALUNO)) * 0.5

calc_mde_vec <- function(power_vec, alpha = 0.05) {
    # Converte poder alvo em Cohen f aproximado para comparação (k=2 grupos)
    # Para k=2, f = d/2; usamos relação d = (z_{1-alpha/2}+z_{power}) * sqrt(2 / n)
    z_alpha <- qnorm(1 - alpha/2)
    sapply(power_vec, function(p) {
        if (is.na(p) || p <= 0) return(NA_real_)          # sem poder / não definido
        if (p >= 0.999) p <- 0.999                        # evita infinito
        z_power <- qnorm(p)
        d <- (z_alpha + z_power) * sqrt(2 / sample_n)     # diferença de médias em SD units (Cohen d)
        f <- d / 2                                        # para dois grupos, f = d/2
        return(f)
    })
}

for (j in 1:4) {
    col_power <- paste0("Model", j)
    col_mde <- paste0("MDE_", col_power)
    mde_table[[col_mde]] <- calc_mde_vec(mde_table[[col_power]])
}

mde_table <- mde_table %>%
    mutate(across(-ATE, ~ round(.x, 2)))

ordem <- c(
    "ATE",
    "Model1", "MDE_Model1",
    "Model2", "MDE_Model2",
    "Model3", "MDE_Model3",
    "Model4", "MDE_Model4"
)
mde_table <- mde_table[, ordem]

# Renomear para exibição
mde_table_display <- mde_table %>%
  rename(`Modelo 1` = Model1, `MDE_Modelo 1` = MDE_Model1,
         `Modelo 2` = Model2, `MDE_Modelo 2` = MDE_Model2,
         `Modelo 3` = Model3, `MDE_Modelo 3` = MDE_Model3,
         `Modelo 4` = Model4, `MDE_Modelo 4` = MDE_Model4)
Figura 1: Função de Poder por Modelo (Aleatorização por Escola)
knitr::kable(mde_table_display)
Tabela 2: MDE (Cohen f) por ATE e Modelo (Aleatorização por Escola)
ATE Modelo 1 MDE_Modelo 1 Modelo 2 MDE_Modelo 2 Modelo 3 MDE_Modelo 3 Modelo 4 MDE_Modelo 4
0.05 0.09 0 0.09 0.00 0.10 0.00 0.10 0.00
0.10 0.02 0 0.07 0.00 0.08 0.00 0.08 0.00
0.15 0.02 0 0.10 0.00 0.09 0.00 0.09 0.00
0.20 0.06 0 0.12 0.00 0.12 0.00 0.12 0.00
0.25 0.08 0 0.14 0.00 0.14 0.00 0.14 0.00
0.30 0.12 0 0.27 0.01 0.24 0.01 0.26 0.01
0.35 0.08 0 0.23 0.01 0.27 0.01 0.28 0.01
0.40 0.08 0 0.23 0.01 0.30 0.01 0.32 0.01
0.45 0.05 0 0.31 0.01 0.38 0.01 0.38 0.01
0.50 0.12 0 0.45 0.01 0.48 0.01 0.51 0.01

1.2 Aleatorização por Alunos

Replicamos o mesmo procedimento, agora com randomização em nível individual (aluno). A variável dependente passa a ser a proficiência em matemática. A Tabela 6 apresenta as probabilidades de rejeição (potência) para cada valor de ATE e especificação de modelo, enquanto a evolução dessa potência ao longo da grade de efeitos está na Figura 5. A fórmula do MDE não é repetida porque continua sendo a da Equação 1.

## ALEATORIZAÇÃO POR ALUNOS ##

mde_alunos <- lapply(effect_grid, function(x) {
    sim_alunos <- lapply(seq_len(MC_REPS), function(i) {
        alunos <- tibble("CD_ALUNO" = df_5_sp$CD_ALUNO %>%
            unique()) %>%
            mutate(treat = rbinom(
                n = length(table(df_5_sp$CD_ALUNO %>%
                    unique())),
                size = 1,
                prob = 0.5
            )) %>%
            left_join(df_5_sp,
                by = "CD_ALUNO",
                multiple = "all"
            ) %>%
            mutate(y = profic_mat + treat * x)

        model <- feols(y ~ treat + csw0(porc_ACERT_lp, porc_ACERT_CIE, factor(TP_SEXO)),
            data = alunos,
            se = "hetero",
            lean = TRUE
        )

        tab <- tibble(
            "rep" = i,
            "reject" = sapply(model, function(x) pvalue(x)["treat"] < alpha),
            "model" = c("Model1", "Model2", "Model3", "Model4")
        )
    })
    sim_alunos <- setDT(do.call(bind_rows, sim_alunos))
    power_table <- tibble(
        "ATE" = x,
        "Model" = unique(sim_alunos$model),
        "power" = sapply(unique(sim_alunos$model), function(x) nrow(sim_alunos[model == x][reject == "TRUE"]) / MC_REPS)
    )
    power_table <- power_table %>% pivot_wider(names_from = "Model", values_from = "power")
    power_table
})
mde_alunos <- do.call(bind_rows, mde_alunos)

mde1_alunos <- mde_alunos %>% pivot_longer(cols = starts_with("Model"), names_to = "Model", values_to = "Power")
mde1_alunos <- mde1_alunos %>% mutate(Model = factor(model_map[Model], levels = paste("Modelo",1:4)))

## Simulação (Aluno -> porcentagem de acerto)
power_student_pct <- simulate_power(df_5_sp, design = "student", outcome = "porc_ACERT_MAT", effect_grid = effect_grid, N = MC_REPS, p_treat = 0.5)
student_pct_summary <- power_student_pct$summary

## Curvas MDE para Aluno -> porcentagem
mde_student_pct <- compute_mde_curve(student_pct_summary)

## Consolidado MDE (parcial – apenas novas combinações)
mde_partial <- bind_rows(
    mde_school_profic %>% mutate(design_outcome = "Escola-Profic"),
    mde_student_pct %>% mutate(design_outcome = "Aluno-PorcAcertos")
) %>%
    mutate(model = model_map[as.character(model)]) %>%
    mutate(model = factor(model, levels = paste("Modelo",1:4)))

## Curvas MDE para os pares (Escola->porc_ACERT_MAT e Aluno->profic_mat)
# Gerar summaries compatíveis (reaproveitando objetos já existentes: mdeE1 e mde1_alunos não incluem se_beta)
# Re-simular rapidamente ate_true=0 para estimar se_beta para esses pares se necessário

power_school_pct <- simulate_power(df_5_sp, design = "school", outcome = "porc_ACERT_MAT", effect_grid = effect_grid, N = MC_REPS, p_treat = 0.5)
power_student_profic <- simulate_power(df_5_sp, design = "student", outcome = "profic_mat", effect_grid = effect_grid, N = MC_REPS, p_treat = 0.5)

mde_school_pct <- compute_mde_curve(power_school_pct$summary)
mde_student_profic <- compute_mde_curve(power_student_profic$summary)

mde_all <- bind_rows(
    mde_school_pct    %>% mutate(design = "school",  outcome = "porc_ACERT_MAT"),
    mde_school_profic %>% mutate(design = "school",  outcome = "profic_mat"),
    mde_student_pct   %>% mutate(design = "student", outcome = "porc_ACERT_MAT"),
    mde_student_profic%>% mutate(design = "student", outcome = "profic_mat")
) %>% mutate(model = model_map[as.character(model)]) %>% mutate(model = factor(model, levels = paste("Modelo",1:4)))
library(dplyr)
tbl_full_mde <- mde_all %>%
    select(design, outcome, model, power_target, MDE) %>%
    arrange(design, outcome, model, power_target) %>%
    group_by(design, outcome, power_target) %>%
    mutate(best = MDE == min(MDE)) %>%
    ungroup()

knitr::kable(tbl_full_mde, digits = 4) %>%
    kable_styling(full_width = FALSE, bootstrap_options = c("striped","hover","condensed")) %>%
    row_spec(which(tbl_full_mde$best), bold = TRUE, background = "#eef9f1") %>%
    scroll_box(width = "100%", height = "400px")
Tabela 3: MDE (t approximation) para poderes alvo por desenho, desfecho e modelo
design outcome model power_target MDE best
school porc_ACERT_MAT Modelo 1 0.7 1.4172 FALSE
school porc_ACERT_MAT Modelo 1 0.8 1.5981 FALSE
school porc_ACERT_MAT Modelo 1 0.9 1.8491 FALSE
school porc_ACERT_MAT Modelo 2 0.7 0.6803 FALSE
school porc_ACERT_MAT Modelo 2 0.8 0.7672 FALSE
school porc_ACERT_MAT Modelo 2 0.9 0.8876 FALSE
school porc_ACERT_MAT Modelo 3 0.7 0.6154 FALSE
school porc_ACERT_MAT Modelo 3 0.8 0.6940 FALSE
school porc_ACERT_MAT Modelo 3 0.9 0.8029 FALSE
school porc_ACERT_MAT Modelo 4 0.7 0.6060 TRUE
school porc_ACERT_MAT Modelo 4 0.8 0.6834 TRUE
school porc_ACERT_MAT Modelo 4 0.9 0.7907 TRUE
school profic_mat Modelo 1 0.7 2.6426 FALSE
school profic_mat Modelo 1 0.8 2.9801 FALSE
school profic_mat Modelo 1 0.9 3.4480 FALSE
school profic_mat Modelo 2 0.7 1.3768 FALSE
school profic_mat Modelo 2 0.8 1.5526 FALSE
school profic_mat Modelo 2 0.9 1.7965 FALSE
school profic_mat Modelo 3 0.7 1.3223 FALSE
school profic_mat Modelo 3 0.8 1.4911 FALSE
school profic_mat Modelo 3 0.9 1.7253 FALSE
school profic_mat Modelo 4 0.7 1.3132 TRUE
school profic_mat Modelo 4 0.8 1.4808 TRUE
school profic_mat Modelo 4 0.9 1.7134 TRUE
student porc_ACERT_MAT Modelo 1 0.7 0.5414 FALSE
student porc_ACERT_MAT Modelo 1 0.8 0.6105 FALSE
student porc_ACERT_MAT Modelo 1 0.9 0.7064 FALSE
student porc_ACERT_MAT Modelo 2 0.7 0.4015 FALSE
student porc_ACERT_MAT Modelo 2 0.8 0.4527 FALSE
student porc_ACERT_MAT Modelo 2 0.9 0.5238 FALSE
student porc_ACERT_MAT Modelo 3 0.7 0.3829 TRUE
student porc_ACERT_MAT Modelo 3 0.8 0.4317 TRUE
student porc_ACERT_MAT Modelo 3 0.9 0.4995 TRUE
student porc_ACERT_MAT Modelo 4 0.7 0.3835 FALSE
student porc_ACERT_MAT Modelo 4 0.8 0.4325 FALSE
student porc_ACERT_MAT Modelo 4 0.9 0.5004 FALSE
student profic_mat Modelo 1 0.7 1.1471 FALSE
student profic_mat Modelo 1 0.8 1.2936 FALSE
student profic_mat Modelo 1 0.9 1.4967 FALSE
student profic_mat Modelo 2 0.7 0.8361 FALSE
student profic_mat Modelo 2 0.8 0.9429 FALSE
student profic_mat Modelo 2 0.9 1.0910 FALSE
student profic_mat Modelo 3 0.7 0.7956 TRUE
student profic_mat Modelo 3 0.8 0.8971 TRUE
student profic_mat Modelo 3 0.9 1.0380 TRUE
student profic_mat Modelo 4 0.7 0.8009 FALSE
student profic_mat Modelo 4 0.8 0.9032 FALSE
student profic_mat Modelo 4 0.9 1.0450 FALSE
ggplot(mde_all, aes(x = power_target, y = MDE, color = model)) +
    geom_line() + geom_point() +
    facet_grid(outcome~design, scales = "free_y") +
    scale_x_continuous(breaks = c(0.7,0.8,0.9)) +
    theme_bw() +
    labs(x = "Poder alvo", y = "MDE", color = "Modelo")
Figura 2: Curvas MDE vs Poder por Desenho e Desfecho
tbl_partial <- mde_partial %>%
    select(design, outcome, model, power_target, MDE) %>%
    arrange(design, outcome, model, power_target)
knitr::kable(tbl_partial, digits = 4) %>%
    kable_styling(full_width = FALSE, bootstrap_options = c("striped","hover","condensed")) %>%
    scroll_box(width = "100%", height = "320px")
Tabela 4: MDE para poderes alvo (0.7,0.8,0.9) – pares Desenho×Desfecho
design outcome model power_target MDE
school profic_mat Modelo 1 0.7 2.6426
school profic_mat Modelo 1 0.8 2.9801
school profic_mat Modelo 1 0.9 3.4480
school profic_mat Modelo 2 0.7 1.3768
school profic_mat Modelo 2 0.8 1.5526
school profic_mat Modelo 2 0.9 1.7965
school profic_mat Modelo 3 0.7 1.3223
school profic_mat Modelo 3 0.8 1.4911
school profic_mat Modelo 3 0.9 1.7253
school profic_mat Modelo 4 0.7 1.3132
school profic_mat Modelo 4 0.8 1.4808
school profic_mat Modelo 4 0.9 1.7134
student porc_ACERT_MAT Modelo 1 0.7 0.5414
student porc_ACERT_MAT Modelo 1 0.8 0.6105
student porc_ACERT_MAT Modelo 1 0.9 0.7064
student porc_ACERT_MAT Modelo 2 0.7 0.4015
student porc_ACERT_MAT Modelo 2 0.8 0.4527
student porc_ACERT_MAT Modelo 2 0.9 0.5238
student porc_ACERT_MAT Modelo 3 0.7 0.3829
student porc_ACERT_MAT Modelo 3 0.8 0.4317
student porc_ACERT_MAT Modelo 3 0.9 0.4995
student porc_ACERT_MAT Modelo 4 0.7 0.3835
student porc_ACERT_MAT Modelo 4 0.8 0.4325
student porc_ACERT_MAT Modelo 4 0.9 0.5004
library(ggplot2)
ggplot(mde_partial, aes(x = power_target, y = MDE, color = model)) +
    geom_line() + geom_point() +
    facet_wrap(~design_outcome, scales = "free_y") +
    scale_x_continuous(breaks = c(0.7,0.8,0.9)) +
    theme_bw() +
    labs(x = "Poder alvo", y = "MDE aproximado", color = "Modelo")
Figura 3: Curvas MDE por Modelo para Escola→Profic e Aluno→Porcentagem
candidate_p <- seq(0.3,0.7,0.1)
effect_grid <- seq(0, 0.5, 0.05)
pt_school_pct  <- explore_p_treat(df_5_sp, design = "school",  outcome = "porc_ACERT_MAT", effect_grid = effect_grid, candidate_p = candidate_p, N = MC_REPS)
pt_school_prof <- explore_p_treat(df_5_sp, design = "school",  outcome = "profic_mat",      effect_grid = effect_grid, candidate_p = candidate_p, N = MC_REPS)
pt_student_pct <- explore_p_treat(df_5_sp, design = "student", outcome = "porc_ACERT_MAT", effect_grid = effect_grid, candidate_p = candidate_p, N = MC_REPS)
pt_student_prof<- explore_p_treat(df_5_sp, design = "student", outcome = "profic_mat",      effect_grid = effect_grid, candidate_p = candidate_p, N = MC_REPS)

pt_all <- bind_rows(pt_school_pct, pt_school_prof, pt_student_pct, pt_student_prof) %>%
    mutate(model = model_map[as.character(model)]) %>%
    mutate(model = factor(model, levels = paste("Modelo",1:4)))

best_p <- pt_all %>% group_by(design, outcome, model) %>% slice_max(order_by = power, n = 1, with_ties = FALSE) %>% ungroup()

tbl_bestp <- best_p %>% select(design, outcome, model, p_treat, power) %>% arrange(design, outcome, model)
knitr::kable(tbl_bestp, digits = 3) %>%
    kable_styling(full_width = FALSE, bootstrap_options = c("striped","hover","condensed")) %>%
    scroll_box(width = "100%", height = "300px")
Tabela 5: Exploração de proporções de tratamento (p_treat) – poder para efeito ~0.25
design outcome model p_treat power
school porc_ACERT_MAT Modelo 1 0.4 0.11
school porc_ACERT_MAT Modelo 2 0.4 0.25
school porc_ACERT_MAT Modelo 3 0.4 0.28
school porc_ACERT_MAT Modelo 4 0.4 0.26
school profic_mat Modelo 1 0.3 0.08
school profic_mat Modelo 2 0.3 0.11
school profic_mat Modelo 3 0.3 0.10
school profic_mat Modelo 4 0.3 0.11
student porc_ACERT_MAT Modelo 1 0.4 0.21
student porc_ACERT_MAT Modelo 2 0.7 0.31
student porc_ACERT_MAT Modelo 3 0.5 0.35
student porc_ACERT_MAT Modelo 4 0.6 0.36
student profic_mat Modelo 1 0.7 0.16
student profic_mat Modelo 2 0.6 0.14
student profic_mat Modelo 3 0.4 0.15
student profic_mat Modelo 4 0.6 0.15
library(ggplot2)
ggplot(pt_all, aes(x = p_treat, y = power, color = model)) +
    geom_line() + geom_point() +
    facet_grid(outcome~design, scales = "free_y") +
    theme_bw() +
    scale_x_continuous(breaks = candidate_p) +
    labs(x = "Proporção tratada", y = "Poder (ATE ≈ 0.25)", color = "Modelo")
Figura 4: Curvas de poder por proporção tratada (efeito ~0.25)
mde_alunos_display <- mde_alunos %>% rename(`Modelo 1`=Model1, `Modelo 2`=Model2, `Modelo 3`=Model3, `Modelo 4`=Model4)
knitr::kable(mde_alunos_display)
Tabela 6: Power por ATE e Modelo (Aleatorização por Aluno)
ATE Modelo 1 Modelo 2 Modelo 3 Modelo 4
0.00 0.05 0.06 0.07 0.07
0.05 0.05 0.05 0.05 0.06
0.10 0.03 0.03 0.03 0.03
0.15 0.05 0.03 0.04 0.08
0.20 0.06 0.08 0.10 0.11
0.25 0.12 0.13 0.12 0.15
0.30 0.06 0.16 0.12 0.13
0.35 0.07 0.13 0.14 0.15
0.40 0.13 0.24 0.23 0.22
0.45 0.16 0.21 0.22 0.22
0.50 0.17 0.31 0.32 0.32
ggplot(data = mde1_alunos, aes(x = ATE, y = Power, group = Model)) +
    geom_line(aes(color = Model)) +
    geom_point(aes(color = Model, shape = Model)) +
    theme_bw() +
    scale_y_continuous(n.breaks = 10) +
    scale_color_brewer(palette = "Dark2", direction = -1) +
    labs(
        x = "ATE",
        y = "Poder"
    )
Figura 5: Função de Poder por Modelo (Aleatorização por Aluno)

2 Questão 2

Enunciado: Quais são os trade-offs entre aleatorizar o tratamento no nível do aluno versus aleatorizar o tratamento no nível da escola? Como você conduziria inferência para cada um desses desenhos? Qual nível de aleatorização você escolheria para esse experimento? Justifique sua resposta.

Aleatorizar no nível do aluno tem apelo porque aumenta a precisão potencial (maior número de unidades independentes) e permite controlar diretamente heterogeneidades observáveis individuais (sexo, raça, desempenho prévio) dentro da regressão, reduzindo variância residual. Entretanto, em um ambiente escolar, a probabilidade de spillover/contágio (compartilhamento de materiais, tutoria informal entre colegas) é elevada; isso viola a SUTVA ao expor, indiretamente, parte do grupo de controle ao mecanismo de tratamento, diluindo o contraste e enviesando para baixo a estimativa do efeito. Além disso, a gestão operacional de aplicar a intervenção seletivamente entre alunos de uma mesma escola tende a ser mais custosa e sujeita a desvios de implementação.

Já a randomização por escola minimiza o risco de contaminação entre grupos, simplifica logística e incentiva aderência homogênea, mas sacrifica poder estatístico por causa da correlação intraescola: o número efetivo de unidades é o de escolas e o “design effect” cresce com o ICC (≈ 1 + (m−1)ρ). Assim, para um mesmo MDE, seriam necessárias mais escolas do que alunos em um desenho individual. Dado o contexto de provável interação intensa entre estudantes, o benefício de preservar a validade interna ao evitar spillovers supera a perda de eficiência. Portanto, apesar do custo em termos de poder, a aleatorização em nível de escola é a estratégia mais coerente para manter um contraste causal limpo e operacionalmente viável.

Aspectos técnicos de inferência: no desenho por escola empregam-se erros-padrão clusterizados; com poucos clusters recomenda-se ajuste CR2 ou randomization inference. No desenho individual usam-se erros-padrão robustos e, havendo correlação intraescola, clusterização por escola. Verificações de balance orientam eventual estratificação ou inclusão pré-especificada de controles. A definição prévia de uma especificação principal mitiga viés de seleção, e ajustes para múltiplas comparações podem ser apropriados quando várias métricas são analisadas.

3 Questão 3

Enunciado: Considere que a aleatorização está sendo feita no nível da escola. São coletados o número de alunos por escola antes e depois da implementação do experimento, e constata-se que, nesse período, o número de alunos nas escolas controle diminuiu, enquanto o número de alunos nas escolas tratadas aumentou. Isso ocorreu porque alguns alunos de escolas do grupo de controle pediram transferência para escolas do grupo de tratamento. Nesse caso, ainda é válido comparar a nota de escolas tratadas com a nota de escolas controle? Se não, como você faria para estimar de forma mais fidedigna o efeito do programa de tutoria?

Quando estudantes originalmente designados ao controle acabam recebendo a intervenção em escolas tratadas (ou quando parte dos alunos de escolas tratadas não a recebe), ocorre não conformidade com a alocação experimental. Isso quebra a ligação direta entre a randomização e quem de fato é exposto, de modo que a diferença simples de médias deixa de identificar o ATE de forma causal. Nessa configuração, o parâmetro relevante passa a ser o LATE: o efeito médio do tratamento sobre o subconjunto de alunos cuja participação é efetivamente induzida pela designação (compliers).

Para recuperar o LATE, utiliza-se tipicamente a designação aleatória (tratamento atribuído à escola) como um instrumento para a variável de recebimento individual (tratamento efetivo). A estratégia de variáveis instrumentais requer (i) relevância: a designação deve aumentar a probabilidade de receber a tutoria; (ii) exogeneidade: a designação é independente de choques não observados que afetam o desempenho; e (iii) monotonicidade (ausência de “defiers”): ninguém que receberia a tutoria sem ser designado deixa de recebê-la por causa da designação. Em um experimento bem implementado, esses requisitos são plausíveis.

Operacionalmente, estima-se primeiro o impacto da designação sobre a taxa de recebimento (primeiro estágio) e, em seguida, o efeito reduzido da designação sobre o desempenho. A razão entre efeito reduzido e efeito no primeiro estágio fornece uma estimativa do LATE. Alternativamente, pode-se ajustar explícita ou implicitamente para a probabilidade de tratamento efetivo (propensity de recebimento) para reforçar a interpretação: o objetivo é atribuir o impacto apenas aos que de fato receberam a tutoria por terem sido designados, mitigando o viés introduzido pela não conformidade.

4 Questão 4

Enunciado: Considere agora que não houve transferências de alunos de escolas de um grupo para o outro. Ainda assim, após o experimento, constata-se que as escolas tratadas têm uma porcentagem maior de alunos prestando a prova do SARESP quando comparado com escolas do grupo de controle. Que tipo de problemas isso pode acarretar na estimação do efeito do programa? O que você faria para contornar ou amenizar essas questões?

O abandono (attrition) passa a ser um problema quando deixa de ser puramente aleatório e passa a refletir características sistemáticas dos participantes. Se, por exemplo, apenas alunas saem da amostra, a estimativa do efeito permanece válida apenas para homens, reduzindo a capacidade de generalização para a população de interesse. Outra via de distorção ocorre quando a saída diferencial altera a comparabilidade entre tratamento e controle, comprometendo a identificação causal.

Se a proporção de estudantes que realizam a prova (SARESP) difere de modo estatisticamente significativo entre escolas tratadas e de controle, há indício de atrito diferencial possivelmente associado ao próprio tratamento, ainda que as características pré-intervenção fossem semelhantes. Nessa situação, a permanência pode tornar-se correlacionada com os resultados potenciais: alguns alunos tratados que permanecem poderiam ter saído se estivessem no controle (ou vice-versa). Caso, por exemplo, estudantes cuja performance seria piorada pelo tratamento tenham maior probabilidade de evadir, a média observada dos tratados tenderá a superestimar o desempenho contrafactual, enviesando a diferença em relação ao grupo de controle.

Uma resposta pragmática é empregar limites (bandas) para o ATT, em linha com abordagens do tipo bounds para attrition seletivo (como a lógica dos Lee bounds). Embora não obtenhamos necessariamente uma estimativa pontual não enviesada para todos os tratados, conseguimos construir um intervalo plausível para o efeito entre os que permaneceram. A ideia básica pode ser ilustrada assim: suponha evasão de 5% no grupo tratado e 10% no controle. Admitindo que os 5% que saíram do tratamento também teriam saído se estivessem no controle, o viés potencial decorre dos 5% “excedentes” que só evadiram no controle. Como não sabemos quais seriam esses indivíduos se tratados, construímos limites. Para o limite superior do impacto, removemos no grupo tratado a fração correspondente (5%) com os menores valores observados de Y1 e reestimamos o efeito; para o limite inferior, removemos os 5% com os maiores valores de Y1 e reestimamos novamente. O intervalo formado por essas duas estimativas fornece uma banda superior e inferior plausível para o verdadeiro efeito do tratamento sob hipóteses mínimas, mitigando o viés introduzido pelo atrito diferencial.

5 Questão 5

Enunciado: A Secretaria quer expandir o programa de tutoria para todo o estado baseando-se nos efeitos estimados do experimento piloto. Quais dificuldades existem ao interpretar os resultados do piloto para prever o impacto estadual? Que fatores poderiam levar a efeitos similares ou diferentes na implementação em larga escala?

A extrapolação dos resultados do piloto para todo o estado enfrenta desafios de validade externa e de execução em escala. Alguns eixos principais:

  1. Heterogeneidade estrutural entre escolas: diferenças em tamanho, recursos, capital humano docente, contexto socioeconômico e gestão podem alterar intensidade e qualidade da tutoria. Um efeito médio na capital ou em escolas urbanas pode não se replicar em escolas rurais ou periferias com menor disponibilidade de alunos tutores qualificados.
  2. Seleção de implementação (“voltage drop”): em expansão, treinamento, supervisão e monitoramento tornam-se mais difíceis de padronizar; a fidelidade ao protocolo cai e o efeito tende a atenuar. Manualização detalhada e supervisão em camadas mitigam, mas não anulam, a perda.
  3. Escassez de tutores elegíveis: maior escala pode levar a recrutamento de alunos tutores menos preparados, reduzindo qualidade marginal da intervenção. Há risco de “diluição” se a densidade de tutores competentes não acompanhar a expansão.
  4. Efeitos gerais de equilíbrio: redistribuição de atenção de professores ou coordenação pedagógica para apoiar o programa pode deslocar recursos de outras atividades, alterando contrafactuais. Em larga escala, externalidades entre escolas (compartilhamento de materiais ou competição) podem surgir e não estavam presentes no piloto.
  5. Medida de resultado e ceiling effects: se a população adicional tiver baseline mais baixo (maior espaço para ganhos) ou mais alto (efeito saturando), o ATE esperado muda. A variância inicial da proficiência é componente crítico do MDE em novos contextos.
  6. Incentivos e compliance: escolas aderentes no piloto podem ser mais motivadas; ao universalizar, escolas com menor engajamento podem apresentar menor taxa de sessões efetivas, reduzindo impacto médio.
  7. Custos logísticos e timing: coordenação de horários extra-classe em massa pode gerar choques de capacidade (salas, equipamentos), afetando intensidade por aluno.

Mitigações e caminhos para extrapolação mais robusta:

  • Coletar e modelar heterogeneidade: estimar efeitos condicionais (CATE) no piloto (ex: por quartis de baseline) e aplicar “reweighting” para aproximar distribuição estadual de covariáveis.
  • Planejar fase intermediária (“scale-up sequencial”): expandir em ondas estratificadas para medir degradação do efeito ao longo do crescimento e ajustar treinamento.
  • Monitorar fidelidade: métricas de dose (número de sessões), participação efetiva e qualidade observacional (checklists) para ajustar suporte.
  • Incorporar análise de custo-efetividade: ao escalar, comparar custo incremental por unidade de ganho de aprendizagem visando priorização orçamentária.
  • Preparar desenho de avaliação contínua (embedded experimentation) durante a expansão, permitindo ajustes iterativos.

Em síntese, efeitos similares dependem de capacidade de replicar a densidade de tutores competentes, garantir supervisão e manter incentivos. Divergências provavelmente emergirão de heterogeneidade estrutural, limitações logísticas e “voltage drop” de implementação. Relatar claramente as características do piloto (mix de escolas, perfil dos tutores, intensidade média) é essencial para interpretar a transferência de impacto.

Referências

Cohen, Jacob. 1988. Statistical Power Analysis for the Behavioral Sciences. 2.ª ed. Lawrence Erlbaum Associates.
Hayes, Richard J., e Lawrence H. Moulton. 2017. Cluster Randomised Trials. 2.ª ed. CRC Press.