Evalid’s two primary uses are the T-Pate function and the PCT(Partial Conjunction Test). In this replication we’ll be demonstrating the T-pate function by replicating the study conducted by Broockman & Kalla (2016) which investigated how attitudes to transphobia may be reduced through door-to-door canvassing. Conducting in Miami Dade county Flordia in 2015 among those who completed a pre-experiment survey. Canvasser’s were randomly assigned to either take the perspective of trans individuals, or a placebo conversation. The outcome was formed by four waves of follow-up surveys which indicated that perspective taking conversations improved the outlook toward trans individuals.
#Evalid is the proprietary package developed by Egami & Hartman
library(evalid)
library(grf)
library(foreign)
library(lmtest)
library(sandwich)
library(survey)
library(MASS)
library(parallel)
library(estimatr)
library(bartCause)
library(tidyverse)
library(knitr)
library(kableExtra)
library(estimatr)
set.seed(29384)
#recoded results
load("~/R Projects/Poli 819/generated/recoded_broockman_kalla_data.RData")
#previous results
load ("~/R Projects/Poli 819/generated/results_bk_external.RData")
#number of bootstrapped samples.
nboot = 1000
## Covariates used for estimation
## Projection models: uses raw age
covariates_proj <- c('vf_age', 'vf_female', 'vf_black', 'vf_white',
names(sample)[str_detect(names(sample), "ideology_t0_factor|religious_t0_factor|pid_t0_factor")][-c(1:3)])
## Weighting models: uses age buckets
covariates <- c('vf_female', 'vf_black', 'vf_white',
names(sample)[str_detect(names(sample), "ideology_t0_factor|religious_t0_factor|pid_t0_factor|vf_age_bucket")][-c(1:4)])
# Pre-specified regression controls used in original analysis
control_vars <- c('miami_trans_law_t0', 'miami_trans_law2_t0', 'therm_trans_t0',
'gender_norms_sexchange_t0', 'gender_norms_moral_t0', 'gender_norms_abnormal_t0',
'ssm_t0', 'therm_obama_t0', 'therm_gay_t0','vf_democrat', 'ideology_t0',
'religious_t0', 'exposure_gay_t0', 'exposure_trans_t0', 'pid_t0', 'sdo_scale',
'gender_norm_daugher_t0', 'gender_norm_looks_t0',
'gender_norm_rights_t0', 'therm_afams_t0', 'vf_female', 'vf_hispanic',
'vf_black', 'vf_age', 'survey_language_es', 'cluster_level_t0_scale_mean')
This section re-analyzes the initial findings from the paper, using the different PATE estimation strategies. The estimators are:
## Only re-runs analysis if no results are loaded.
## run analysis for each time period
if(!exists("plot_data_tti")) {
plot_data_tti <- NULL
outcome_vars <- c("trans.tolerance.dv.t1" , "trans.tolerance.dv.t2",
"trans.tolerance.dv.t3", "trans.tolerance.dv.t4")
for(outcome in outcome_vars) {
# limit to rows without missing outcome
exp_data <- sample %>% filter(!is.na(sample[, outcome]))
# create formulas for analysis with outcome
formula_outcome <- as.formula(paste0(outcome, " ~ ", paste0(covariates, collapse = " + ")))
formula_outcome_proj <- as.formula(paste0(outcome, " ~ ", paste0(covariates_proj, collapse = " + ")))
formula_outcome_wls <- as.formula(paste0(outcome, " ~ ", paste0(control_vars, collapse = " + ")))
formula_weights <- as.formula(paste0("S ~ ", paste0(covariates, collapse = " + ")))
## Sate Estimate
sate_est <- data.frame(estimator = c("SATE"), type = "SATE",
tpate(formula_outcome = formula_outcome_wls,
formula_weights = formula_weights,
exp_data = exp_data, pop_data = exp_data,
treatment = "treat_ind",
id_cluster = exp_data$block_ind,
est_type = "wls", weights_type = "calibration",
sims = nboot,
compute_sate = FALSE)$tpate[c("est", "se", "ci_lower", "ci_upper")] %>% data.frame())
## PATE Estimates
## Weighting: IPW
ipw_cal <- data.frame(estimator = "ipw-cal", type = "weighting",
tpate(formula_outcome = formula_outcome,
formula_weights = formula_weights,
exp_data = exp_data, pop_data = pop,
treatment = "treat_ind",
id_cluster = exp_data$block_ind,
est_type = "ipw", weights_type = "calibration",
sims = nboot,
weights_max = 10,
compute_sate = FALSE)$tpate[c("est", "se", "ci_lower", "ci_upper")]
%>% data.frame())
## Weighting: Weighted Least Squares
wls_cal <- data.frame(estimator = "wls-cal", type = "weighting",
tpate(formula_outcome = formula_outcome_wls,
formula_weights = formula_weights,
exp_data = exp_data, pop_data = pop,
treatment = "treat_ind",
id_cluster = exp_data$block_ind,
est_type = "wls", weights_type = "calibration",
sims = nboot,
weights_max = 10,
compute_sate = FALSE)$tpate[c("est", "se", "ci_lower", "ci_upper")]
%>% data.frame())
## Outcome: Regression
out_ols <- data.frame(estimator = "OLS-proj", type = "outcome",
tpate(formula_outcome = formula_outcome_proj,
formula_weights = formula_weights,
exp_data = exp_data, pop_data = pop,
treatment = "treat_ind",
id_cluster = exp_data$block_ind,
est_type = "outcome-ols",
sims = nboot,
weights_max = 10,
compute_sate = FALSE)$tpate[c("est", "se", "ci_lower", "ci_upper")]
%>% data.frame())
## Outcome: BART
out_bart <- data.frame(estimator = "BART-proj", type = "outcome",
tpate(formula_outcome = formula_outcome_proj,
formula_weights = formula_weights,
exp_data = exp_data, pop_data = pop,
treatment = "treat_ind",
id_cluster = exp_data$block_ind,
est_type = "outcome-bart",
sims = nboot,
weights_max = 10,
compute_sate = FALSE)$tpate[c("est", "se", "ci_lower", "ci_upper")]
%>% data.frame())
## Doubly Robust Estimators
## Doubly Robust: Augmented-Regression
dr_cal_ols <- data.frame(estimator = "DR-OLS-cal", type = "doubly robust",
tpate(formula_outcome = formula_outcome,
formula_weights = formula_weights,
exp_data = exp_data, pop_data = pop,
treatment = "treat_ind",
id_cluster = exp_data$block_ind,
weights_type = "calibration",
est_type = "dr-ols",
sims = nboot,
weights_max = 10,
compute_sate = FALSE)$tpate[c("est", "se", "ci_lower", "ci_upper")]
%>% data.frame())
## Doubly Robust: Augmented-BART
dr_cal_bart <- data.frame(estimator = "DR-BART-cal", type = "doubly robust",
tpate(formula_outcome = formula_outcome_proj,
formula_weights = formula_weights,
exp_data = exp_data, pop_data = pop,
treatment = "treat_ind",
id_cluster = exp_data$block_ind,
weights_type = "calibration",
est_type = "dr-bart",
sims = nboot,
weights_max = 10,
compute_sate = FALSE)$tpate[c("est", "se", "ci_lower", "ci_upper")]
%>% data.frame())
results = data.frame(time = which(outcome_vars == outcome),
bind_rows(
sate_est,
ipw_cal,
wls_cal,
out_ols,
out_bart,
dr_cal_ols,
dr_cal_bart
)
)
plot_data_tti <- bind_rows(plot_data_tti, results)
}
# Format name columns
plot_data_tti$time_name = factor(plot_data_tti$time, labels = c("+3 Days", "+3 Weeks", "+6 Weeks", "+3 Months"))
plot_data_tti$estimator_type = factor(case_when(str_detect(plot_data_tti$type, "SATE") ~ "SATE",
str_detect(plot_data_tti$type, "outcome") ~ "T-PATE:\nOutcome-based Estimator",
str_detect(plot_data_tti$type, "doubly robust") ~ "T-PATE:\nDoubly Robust Estimator",
TRUE ~ "T-PATE:\nWeighting-based Estimator"),
levels = c("SATE", "T-PATE:\nWeighting-based Estimator",
"T-PATE:\nOutcome-based Estimator",
"T-PATE:\nDoubly Robust Estimator"))
plot_data_tti$estimator_name = factor(case_when(plot_data_tti$estimator == "SATE" ~ "OLS",
plot_data_tti$estimator == "ipw-cal" ~ "IPW",
plot_data_tti$estimator == "wls-cal" ~ "wLS",
plot_data_tti$estimator == "OLS-proj" ~ "OLS",
plot_data_tti$estimator == "BART-proj" ~ "BART",
plot_data_tti$estimator == "DR-OLS-cal" ~ "AIPW\nwith OLS",
plot_data_tti$estimator == "DR-BART-cal" ~ "AIPW\nwith BART"),
levels = c("OLS", "IPW", "wLS", "BART", "AIPW\nwith OLS", "AIPW\nwith BART"))}
## Save results
#save(plot_data_tti, file = paste0("./generated/main_results/results_bk_external.RData"))
dw = 0.5
plot_data_tti %>%
ggplot(aes(x = estimator_name, y = est, color = estimator_type)) +
scale_color_manual(values=c("black", "red", "blue", "magenta")) +
geom_linerange(aes(ymin = ci_lower, ymax = ci_upper), position = position_dodge(width = dw)) +
geom_point(aes(y = est), position = position_dodge(width = dw)) +
theme_bw() +
xlab("") +
ylab("Estimated Causal Effects on Transgender Tolerance Scale") +
theme(axis.title.y = element_text(size = 13, margin = margin(t = 0, r = 10, b = 0, l = 0)))+
geom_hline(yintercept = 0, linetype = 2) +
theme(legend.position="none",
axis.text.x = element_text(angle = 0, size = 11, margin = margin(t = 10, r = 0, b = 0, l = 0),
colour = "black"),
axis.text = element_text(size = 11),
axis.title = element_text(size = 11),
legend.text = element_text(size = 11),
panel.grid.major = element_blank(),
strip.text.x = element_text(size = 11),
strip.text.y = element_text(size = 13)) +
facet_grid(time_name ~ estimator_type, scales = "free_x")
#ggsave("./generated/Figures/Figure_7.pdf", height = 8, width = 11)