The conjoint formula is derived based on the author’s code. It was not initially intuitive that these are the necessary factors based on the title of the figure, which affected the initial results. However, after the conjoint formula was fixed, the figures derived were exactly the same.
# Look at data
table(data$respondent_type)
##
## Citizen Politician
## 53760 26298
table(data$country)
##
## Belgium Chile Denmark United States
## 21360 17150 23820 17728
table(data$woman_pol)
##
## Man politician Woman politician
## 40095 39913
table(data$woman_user)
##
## Woman user Man user
## 39937 40071
table(data$party_pol_copartisan)
##
## Non co-partisan Co-partisan
## 68221 11837
table(data$gendered)
##
## Non-gendered text Gendered text
## 40112 39896
table(data$chose_profile)
##
## 0 1
## 36321 36321
table(data$text_pol)
##
## PolText01 PolText02 PolText03 PolText04 PolText05 PolText06 PolText07 PolText08
## 4043 3990 3905 4127 3990 4022 3925 3990
## PolText09 PolText10 PolText11 PolText12 PolText13 PolText14 PolText15 PolText16
## 4082 4002 3992 3994 3995 3947 4036 4080
## PolText17 PolText18 PolText19 PolText20
## 3917 4008 3952 4011
table(data$text_user)
##
## UserText01 UserText02 UserText03 UserText04 UserText05 UserText06 UserText07
## 5036 5121 5027 4925 4949 4986 4909
## UserText08 UserText09 UserText10 UserText11 UserText12 UserText13 UserText14
## 4927 4997 5015 5070 5087 4970 4930
## UserText15 UserText16
## 5116 4943
# Factor
data$respondent_type <- factor(data$respondent_type, levels = c("Citizen", "Politician"))
# subset data -> politician vs citizen
pol_data <- subset(data,respondent_type == "Politician")
cit_data <- subset(data,respondent_type == "Citizen")
vig_pol <- subset(vig, respondent_type == "Politician")
vig_cit <- subset(vig, respondent_type == "Citizen")
# conjoint formula
cj_formula <- chose_profile ~ text_pol +
text_user +
party_pol_copartisan +
woman_user +
woman_pol +
gendered
All the codes are done with the package “cregg”.
# 1. AMCE estimates (per country + pooled)
# Country subsets
pol_us <- subset(pol_data, country == "United States")
pol_dk <- subset(pol_data, country == "Denmark")
pol_cl <- subset(pol_data, country == "Chile")
pol_be <- subset(pol_data, country == "Belgium")
# AMCE by country
amce_us <- amce(cj_formula, data = pol_us, id = ~ id)
amce_dk <- amce(cj_formula, data = pol_dk, id = ~ id)
amce_cl <- amce(cj_formula, data = pol_cl, id = ~ id)
amce_be <- amce(cj_formula, data = pol_be, id = ~ id)
# combine into df
df_us <- as.data.frame(amce_us); df_us$country <- "United States"
df_dk <- as.data.frame(amce_dk); df_dk$country <- "Denmark"
df_cl <- as.data.frame(amce_cl); df_cl$country <- "Chile"
df_be <- as.data.frame(amce_be); df_be$country <- "Belgium"
plot_df <- rbind(df_us, df_dk, df_cl, df_be)
# Pooled AMCE (politician sample)
amce_pooled <- amce(cj_formula, data = pol_data, id = ~ id)
pooled_df <- as.data.frame(amce_pooled)
pooled_df$country <- "Pooled"
# Use percentage points to match the figure
plot_df$estimate <- plot_df$estimate * 100
plot_df$lower <- plot_df$lower * 100
plot_df$upper <- plot_df$upper * 100
pooled_df$estimate <- pooled_df$estimate * 100
pooled_df$lower <- pooled_df$lower * 100
pooled_df$upper <- pooled_df$upper * 100
A helper function is used to draw the panels since this step is repeated throughout the figure which is the preferred method over manually code all the variables.
# 2. Helper function
plot_amce_panel <- function(feature_name, y_levels, y_label, main_title) {
panel <- subset(plot_df, feature == feature_name)
pooled <- subset(pooled_df, feature == feature_name)
all_dat <- rbind(panel, pooled)
# order levels
all_dat$level <- factor(all_dat$level, levels = y_levels)
# split into country treatment, pooled treatment, pooled baseline
by_country <- subset(all_dat, country != "Pooled" & !is.na(std.error))
pooled_treat <- subset(all_dat, country == "Pooled" & !is.na(std.error))
pooled_base <- subset(all_dat, country == "Pooled" & is.na(std.error))
ggplot() +
geom_vline(xintercept = 0) +
# country-specific treatment points + CIs
geom_point(data = by_country,
aes(x = estimate, y = level, colour = country),
position = position_dodge(width = 0.6), size = 2.5) +
geom_errorbarh(data = by_country,
aes(xmin = lower, xmax = upper, y = level, colour = country),
position = position_dodge(width = 0.6), height = 0) +
# pooled treatment (diamond)
geom_point(
data = pooled_treat,
aes(x = estimate, y = level),
shape = 23, fill = "white", colour = "black",
size = 4, stroke = 1.2
) +
geom_errorbarh(
data = pooled_treat,
aes(xmin = lower, xmax = upper, y = level),
height = 0, colour = "black"
) +
# pooled baseline (dot)
geom_point(
data = pooled_base,
aes(x = estimate, y = level),
shape = 16, colour = "black", size = 2.5
) +
scale_x_continuous(breaks = seq(-4, 12, by = 2)) +
coord_cartesian(xlim = c(-4, 12)) +
scale_y_discrete(limits = y_levels, drop = FALSE) +
labs(
x = "AMCE (percentage points)",
y = y_label,
title = main_title,
subtitle = "Politician sample only, by country"
) +
theme_minimal(base_size = 13)
}
The plots derived are exactly the same as the plots in Fig 3.
# 3. Plots
# 1) Gender of politician
plot_gender_pol <- plot_amce_panel(
feature_name = "woman_pol",
y_levels = c("Man politician", "Woman politician"),
y_label = "Gender of politician",
main_title = "Effect of Politician's Gender on Toxicity Perceptions"
)
# 2) Gendered text
plot_gendered_text <- plot_amce_panel(
feature_name = "gendered",
y_levels = c("Non-gendered text", "Gendered text"),
y_label = "Gendered text",
main_title = "Effect of Gendered Text on Toxicity Perceptions"
)
# 3) Gender of user
plot_gender_user <- plot_amce_panel(
feature_name = "woman_user",
y_levels = c("Woman user", "Man user"),
y_label = "Gender of user",
main_title = "Effect of User's Gender on Toxicity Perceptions"
)
# 4) Co-partisan politician
plot_copartisan <- plot_amce_panel(
feature_name = "party_pol_copartisan",
y_levels = c("Non co-partisan", "Co-partisan"),
y_label = "Co-partisan politician",
main_title = "Effect of Co-partisanship on Toxicity Perceptions"
)
plot_gender_pol
plot_gendered_text
plot_gender_user
plot_copartisan
# 1. AMCE estimates
# country subsets (citizen)
cit_us <- subset(cit_data, country == "United States")
cit_dk <- subset(cit_data, country == "Denmark")
cit_cl <- subset(cit_data, country == "Chile")
cit_be <- subset(cit_data, country == "Belgium")
# AMCE by country
amce_us_cit <- amce(cj_formula, data = cit_us, id = ~ id)
amce_dk_cit <- amce(cj_formula, data = cit_dk, id = ~ id)
amce_cl_cit <- amce(cj_formula, data = cit_cl, id = ~ id)
amce_be_cit <- amce(cj_formula, data = cit_be, id = ~ id)
# combine into df
df_us_cit <- as.data.frame(amce_us_cit); df_us_cit$country <- "United States"
df_dk_cit <- as.data.frame(amce_dk_cit); df_dk_cit$country <- "Denmark"
df_cl_cit <- as.data.frame(amce_cl_cit); df_cl_cit$country <- "Chile"
df_be_cit <- as.data.frame(amce_be_cit); df_be_cit$country <- "Belgium"
plot_df_cit <- rbind(df_us_cit, df_dk_cit, df_cl_cit, df_be_cit)
# pooled AMCE (citizen)
amce_pooled_cit <- amce(cj_formula, data = cit_data, id = ~ id)
pooled_df_cit <- as.data.frame(amce_pooled_cit)
pooled_df_cit$country <- "Pooled"
# percentage points
plot_df_cit$estimate <- plot_df_cit$estimate * 100
plot_df_cit$lower <- plot_df_cit$lower * 100
plot_df_cit$upper <- plot_df_cit$upper * 100
pooled_df_cit$estimate <- pooled_df_cit$estimate * 100
pooled_df_cit$lower <- pooled_df_cit$lower * 100
pooled_df_cit$upper <- pooled_df_cit$upper * 100
# 2. Helper
plot_amce_panel_cit <- function(feature_name, y_levels, y_label, main_title) {
panel <- subset(plot_df_cit, feature == feature_name)
pooled <- subset(pooled_df_cit, feature == feature_name)
all_dat <- rbind(panel, pooled)
# order levels (baseline then treatment)
all_dat$level <- factor(all_dat$level, levels = y_levels)
# split into country treatment, pooled treatment, pooled baseline
by_country <- subset(all_dat, country != "Pooled" & !is.na(std.error))
pooled_treat <- subset(all_dat, country == "Pooled" & !is.na(std.error))
pooled_base <- subset(all_dat, country == "Pooled" & is.na(std.error))
ggplot() +
geom_vline(xintercept = 0) +
# country-specific treatment points & CIs
geom_point(data = by_country,
aes(x = estimate, y = level, colour = country),
position = position_dodge(width = 0.6), size = 2.5) +
geom_errorbarh(data = by_country,
aes(xmin = lower, xmax = upper, y = level, colour = country),
position = position_dodge(width = 0.6), height = 0) +
# pooled treatment (diamond)
geom_point(
data = pooled_treat,
aes(x = estimate, y = level),
shape = 23, fill = "white", colour = "black",
size = 4, stroke = 1.2
) +
geom_errorbarh(
data = pooled_treat,
aes(xmin = lower, xmax = upper, y = level),
height = 0, colour = "black"
) +
# pooled baseline (dot)
geom_point(
data = pooled_base,
aes(x = estimate, y = level),
shape = 16, colour = "black", size = 2.5
) +
scale_x_continuous(breaks = seq(-4, 12, by = 2)) +
coord_cartesian(xlim = c(-4, 12)) +
scale_y_discrete(limits = y_levels, drop = FALSE) +
labs(
x = "AMCE (percentage points)",
y = y_label,
title = main_title,
subtitle = "Citizen sample only, by country"
) +
theme_minimal(base_size = 13)
}
# 3. Plots
# 1) gender of politician
plot_gender_pol_cit <- plot_amce_panel_cit(
feature_name = "woman_pol",
y_levels = c("Man politician", "Woman politician"),
y_label = "Gender of politician",
main_title = "Effect of Politician's Gender on Toxicity Perceptions"
)
# 2) Ggndered text
plot_gendered_text_cit <- plot_amce_panel_cit(
feature_name = "gendered",
y_levels = c("Non-gendered text", "Gendered text"),
y_label = "Gendered text",
main_title = "Effect of Gendered Text on Toxicity Perceptions"
)
# 3) user gender
plot_gender_user_cit <- plot_amce_panel_cit(
feature_name = "woman_user",
y_levels = c("Woman user", "Man user"),
y_label = "Gender of user",
main_title = "Effect of User's Gender on Toxicity Perceptions"
)
# 4) co-partisan politician
plot_copartisan_cit <- plot_amce_panel_cit(
feature_name = "party_pol_copartisan",
y_levels = c("Non co-partisan", "Co-partisan"),
y_label = "Co-partisan politician",
main_title = "Effect of Co-partisanship on Toxicity Perceptions"
)
plot_gender_pol_cit
plot_gendered_text_cit
plot_gender_user_cit
plot_copartisan_cit
# 4A: politician gender × gendered text
# Base terms + dummy for woman politician × gendered text
cj_pol_gentext <- chose_profile ~
text_pol +
text_user +
party_pol_copartisan +
woman_user +
woman_pol +
gendered +
woman_pol_gendered
# 4B: politician gender × user gender
# Base terms + dummy for woman politician × man user
cj_pol_usergender <- chose_profile ~
text_pol +
text_user +
party_pol_copartisan +
woman_user +
woman_pol +
gendered +
woman_pol_man_user
amce_pol_4A <- amce(cj_pol_gentext, data = pol_data, id = ~ id)
amce_cit_4A <- amce(cj_pol_gentext, data = cit_data, id = ~ id)
amce_pol_4B <- amce(cj_pol_usergender, data = pol_data, id = ~ id)
amce_cit_4B <- amce(cj_pol_usergender, data = cit_data, id = ~ id)
df_pol_4A <- as.data.frame(amce_pol_4A); df_pol_4A$sample <- "Politician sample"
df_cit_4A <- as.data.frame(amce_cit_4A); df_cit_4A$sample <- "Citizen sample"
fig4A <- rbind(df_pol_4A, df_cit_4A)
fig4A$sample <- factor(fig4A$sample, levels = c("Politician sample", "Citizen sample"))
df_pol_4B <- as.data.frame(amce_pol_4B); df_pol_4B$sample <- "Politician sample"
df_cit_4B <- as.data.frame(amce_cit_4B); df_cit_4B$sample <- "Citizen sample"
fig4B <- rbind(df_pol_4B, df_cit_4B)
fig4B$sample <- factor(fig4B$sample, levels = c("Politician sample", "Citizen sample"))
# percentage points
fig4A$estimate <- fig4A$estimate * 100
fig4A$lower <- fig4A$lower * 100
fig4A$upper <- fig4A$upper * 100
fig4B$estimate <- fig4B$estimate * 100
fig4B$lower <- fig4B$lower * 100
fig4B$upper <- fig4B$upper * 100
# Interaction row: 2 points (citizen, politician), no baseline
plot_fig4_interaction <- function(df, feature_name, y_label, main_title) {
panel <- subset(df, feature == feature_name & !is.na(std.error))
panel$level <- factor(y_label, levels = y_label)
ggplot(panel,
aes(x = estimate, y = level, colour = sample)) +
geom_vline(xintercept = 0) +
geom_point(size = 2.5, position = position_dodge(width = 0.4)) +
geom_errorbarh(aes(xmin = lower, xmax = upper),
height = 0,
position = position_dodge(width = 0.4)) +
scale_x_continuous(breaks = seq(-4, 12, by = 2)) +
coord_cartesian(xlim = c(-4, 12)) +
labs(
x = "AMCE (percentage points)",
y = "",
title = main_title
) +
theme_minimal(base_size = 13) +
theme(legend.position = "top")
}
plot_fig4_main <- function(df, feature_name, y_levels, y_label, main_title) {
panel <- subset(df, feature == feature_name)
panel$level <- factor(panel$level, levels = y_levels)
baseline <- subset(panel, is.na(std.error))
if (nrow(baseline) > 0) baseline <- baseline[1, , drop = FALSE]
by_sample <- subset(panel, !is.na(std.error))
ggplot() +
geom_vline(xintercept = 0) +
geom_point(data = by_sample,
aes(x = estimate, y = level, colour = sample),
size = 2.5, position = position_dodge(width = 0.4)) +
geom_errorbarh(data = by_sample,
aes(xmin = lower, xmax = upper, y = level, colour = sample),
height = 0, position = position_dodge(width = 0.4)) +
geom_point(data = baseline,
aes(x = estimate, y = level),
shape = 16, colour = "black", size = 2.5) +
scale_x_continuous(breaks = seq(-4, 12, by = 2)) +
coord_cartesian(xlim = c(-4, 12)) +
scale_y_discrete(limits = y_levels, drop = FALSE) +
labs(
x = "AMCE (percentage points)",
y = y_label,
title = main_title
) +
theme_minimal(base_size = 13) +
theme(legend.position = "top")
}
## 5. A plots (politician gender × gendered text)
fig4a_interaction <- plot_fig4_interaction(
df = fig4A,
feature_name = "woman_pol_gendered",
y_label = "Woman politician × gendered text",
main_title = "Interaction: Politician gender × gendered text"
)
fig4a_polgender <- plot_fig4_main(
df = fig4A,
feature_name = "woman_pol",
y_levels = c("Man politician", "Woman politician"),
y_label = "Gender of politician",
main_title = "Gender of politician"
)
fig4a_gendered <- plot_fig4_main(
df = fig4A,
feature_name = "gendered",
y_levels = c("Non-gendered text", "Gendered text"),
y_label = "Gendered text",
main_title = "Gendered text"
)
## 6. B plots (politician gender × user gender)
fig4b_interaction <- plot_fig4_interaction(
df = fig4B,
feature_name = "woman_pol_man_user",
y_label = "Woman politician × man user",
main_title = "Interaction: Politician gender × user gender"
)
fig4b_polgender <- plot_fig4_main(
df = fig4B,
feature_name = "woman_pol",
y_levels = c("Man politician", "Woman politician"),
y_label = "Gender of politician",
main_title = "Gender of politician"
)
fig4b_usergender <- plot_fig4_main(
df = fig4B,
feature_name = "woman_user",
y_levels = c("Woman user", "Man user"),
y_label = "Gender of user",
main_title = "Gender of user"
)
fig4a_interaction
fig4a_polgender
fig4a_gendered
fig4b_interaction
fig4b_polgender
fig4b_usergender
# 1.AMCEs for each subgroup and keep woman-politician effect
# Helper: only woman-politician row
extract_woman_pol <- function(amce_obj) {
df <- as.data.frame(amce_obj)
df <- subset(df, feature == "woman_pol" & level == "Woman politician")
df[, c("estimate", "lower", "upper")]
}
fig5_rows <- list()
cj_formula_copartisan <- chose_profile ~ text_pol +
text_user +
woman_user +
woman_pol +
gendered
# Additional formula for co-partisan split (no party_pol_copartisan)
# Politician
# respondent gender
amce_pol_gender_w <- amce(cj_formula,
data = subset(pol_data, resp_gender == "Female"),
id = ~ id)
temp <- extract_woman_pol(amce_pol_gender_w)
temp$group <- "Respondent gender"
temp$subgroup <- "Woman"
temp$sample <- "Politician sample"
fig5_rows[[length(fig5_rows) + 1]] <- temp
amce_pol_gender_m <- amce(cj_formula,
data = subset(pol_data, resp_gender == "Male"),
id = ~ id)
temp <- extract_woman_pol(amce_pol_gender_m)
temp$group <- "Respondent gender"
temp$subgroup <- "Man"
temp$sample <- "Politician sample"
fig5_rows[[length(fig5_rows) + 1]] <- temp
# respondent ideology
amce_pol_ideo_r <- amce(cj_formula,
data = subset(pol_data, resp_ideology_discrete == "Right-wing"),
id = ~ id)
temp <- extract_woman_pol(amce_pol_ideo_r)
temp$group <- "Respondent ideology"
temp$subgroup <- "Right-wing"
temp$sample <- "Politician sample"
fig5_rows[[length(fig5_rows) + 1]] <- temp
amce_pol_ideo_l <- amce(cj_formula,
data = subset(pol_data, resp_ideology_discrete == "Left-wing"),
id = ~ id)
temp <- extract_woman_pol(amce_pol_ideo_l)
temp$group <- "Respondent ideology"
temp$subgroup <- "Left-wing"
temp$sample <- "Politician sample"
fig5_rows[[length(fig5_rows) + 1]] <- temp
# co-partisan with politician
amce_pol_copart_non <- amce(cj_formula_copartisan,
data = subset(pol_data, party_pol_copartisan == "Non co-partisan"),
id = ~ id)
temp <- extract_woman_pol(amce_pol_copart_non)
temp$group <- "Respondent is a co-partisan of the politician"
temp$subgroup <- "Non co-partisan"
temp$sample <- "Politician sample"
fig5_rows[[length(fig5_rows) + 1]] <- temp
amce_pol_copart_co <- amce(cj_formula_copartisan,
data = subset(pol_data, party_pol_copartisan == "Co-partisan"),
id = ~ id)
temp <- extract_woman_pol(amce_pol_copart_co)
temp$group <- "Respondent is a co-partisan of the politician"
temp$subgroup <- "Co-partisan"
temp$sample <- "Politician sample"
fig5_rows[[length(fig5_rows) + 1]] <- temp
# social media harassment experience
amce_pol_harass_no <- amce(cj_formula,
data = subset(pol_data,
resp_exposure_binary ==
"Has not experienced social media harassment"),
id = ~ id)
temp <- extract_woman_pol(amce_pol_harass_no)
temp$group <- "Respondent experience with social media harassment"
temp$subgroup <- "No exp. w/ harassment"
temp$sample <- "Politician sample"
fig5_rows[[length(fig5_rows) + 1]] <- temp
amce_pol_harass_yes <- amce(cj_formula,
data = subset(pol_data,
resp_exposure_binary ==
"Experienced social media harassment"),
id = ~ id)
temp <- extract_woman_pol(amce_pol_harass_yes)
temp$group <- "Respondent experience with social media harassment"
temp$subgroup <- "Exp. w/ harassment"
temp$sample <- "Politician sample"
fig5_rows[[length(fig5_rows) + 1]] <- temp
# citizen
# respondent gender
amce_cit_gender_w <- amce(cj_formula,
data = subset(cit_data, resp_gender == "Female"),
id = ~ id)
temp <- extract_woman_pol(amce_cit_gender_w)
temp$group <- "Respondent gender"
temp$subgroup <- "Woman"
temp$sample <- "Citizen sample"
fig5_rows[[length(fig5_rows) + 1]] <- temp
amce_cit_gender_m <- amce(cj_formula,
data = subset(cit_data, resp_gender == "Male"),
id = ~ id)
temp <- extract_woman_pol(amce_cit_gender_m)
temp$group <- "Respondent gender"
temp$subgroup <- "Man"
temp$sample <- "Citizen sample"
fig5_rows[[length(fig5_rows) + 1]] <- temp
# respondent ideology
amce_cit_ideo_r <- amce(cj_formula,
data = subset(cit_data, resp_ideology_discrete == "Right-wing"),
id = ~ id)
temp <- extract_woman_pol(amce_cit_ideo_r)
temp$group <- "Respondent ideology"
temp$subgroup <- "Right-wing"
temp$sample <- "Citizen sample"
fig5_rows[[length(fig5_rows) + 1]] <- temp
amce_cit_ideo_l <- amce(cj_formula,
data = subset(cit_data, resp_ideology_discrete == "Left-wing"),
id = ~ id)
temp <- extract_woman_pol(amce_cit_ideo_l)
temp$group <- "Respondent ideology"
temp$subgroup <- "Left-wing"
temp$sample <- "Citizen sample"
fig5_rows[[length(fig5_rows) + 1]] <- temp
## co-partisan with politician
amce_cit_copart_non <- amce(cj_formula_copartisan,
data = subset(cit_data, party_pol_copartisan == "Non co-partisan"),
id = ~ id)
temp <- extract_woman_pol(amce_cit_copart_non)
temp$group <- "Respondent is a co-partisan of the politician"
temp$subgroup <- "Non co-partisan"
temp$sample <- "Citizen sample"
fig5_rows[[length(fig5_rows) + 1]] <- temp
amce_cit_copart_co <- amce(cj_formula_copartisan,
data = subset(cit_data, party_pol_copartisan == "Co-partisan"),
id = ~ id)
temp <- extract_woman_pol(amce_cit_copart_co)
temp$group <- "Respondent is a co-partisan of the politician"
temp$subgroup <- "Co-partisan"
temp$sample <- "Citizen sample"
fig5_rows[[length(fig5_rows) + 1]] <- temp
# social media harassment experience
amce_cit_harass_no <- amce(cj_formula,
data = subset(cit_data,
resp_exposure_binary ==
"Has not experienced social media harassment"),
id = ~ id)
temp <- extract_woman_pol(amce_cit_harass_no)
temp$group <- "Respondent experience with social media harassment"
temp$subgroup <- "No exp. w/ harassment"
temp$sample <- "Citizen sample"
fig5_rows[[length(fig5_rows) + 1]] <- temp
amce_cit_harass_yes <- amce(cj_formula,
data = subset(cit_data,
resp_exposure_binary ==
"Experienced social media harassment"),
id = ~ id)
temp <- extract_woman_pol(amce_cit_harass_yes)
temp$group <- "Respondent experience with social media harassment"
temp$subgroup <- "Exp. w/ harassment"
temp$sample <- "Citizen sample"
fig5_rows[[length(fig5_rows) + 1]] <- temp
# 2. Combine rows into one data frame
fig5 <- rbind(
fig5_rows[[1]], fig5_rows[[2]], fig5_rows[[3]], fig5_rows[[4]],
fig5_rows[[5]], fig5_rows[[6]], fig5_rows[[7]], fig5_rows[[8]],
fig5_rows[[9]], fig5_rows[[10]], fig5_rows[[11]], fig5_rows[[12]],
fig5_rows[[13]], fig5_rows[[14]], fig5_rows[[15]], fig5_rows[[16]]
)
# order panels and subgroup labels
fig5$group <- factor(
fig5$group,
levels = c(
"Respondent gender",
"Respondent ideology",
"Respondent is a co-partisan of the politician",
"Respondent experience with social media harassment"
)
)
fig5$subgroup <- factor(
fig5$subgroup,
levels = c(
"Woman", "Man",
"Right-wing", "Left-wing",
"Non co-partisan", "Co-partisan",
"No exp. w/ harassment", "Exp. w/ harassment"
)
)
# percentage points
fig5$estimate <- fig5$estimate * 100
fig5$lower <- fig5$lower * 100
fig5$upper <- fig5$upper * 100
# 3. Plots
fig5_pol <- subset(fig5, sample == "Politician sample")
fig5_cit <- subset(fig5, sample == "Citizen sample")
fig5_pol_plot <- ggplot(fig5_pol,
aes(x = estimate, y = subgroup)) +
geom_vline(xintercept = 0) +
geom_point(size = 2.5) +
geom_errorbarh(aes(xmin = lower, xmax = upper), height = 0) +
facet_grid(group ~ ., scales = "free_y") +
scale_x_continuous(breaks = seq(0, 10, by = 2)) +
coord_cartesian(xlim = c(0, 10)) +
labs(
x = "AMCE (percentage points)\nfor whether the politician is a woman",
y = "",
title = "Politician sample"
) +
theme_minimal(base_size = 12) +
theme(strip.text.y = element_blank())
fig5_cit_plot <- ggplot(fig5_cit,
aes(x = estimate, y = subgroup)) +
geom_vline(xintercept = 0) +
geom_point(size = 2.5) +
geom_errorbarh(aes(xmin = lower, xmax = upper), height = 0) +
facet_grid(group ~ ., scales = "free_y") +
scale_x_continuous(breaks = seq(0, 10, by = 2)) +
coord_cartesian(xlim = c(0, 10)) +
labs(
x = "AMCE (percentage points)\nfor whether the politician is a woman",
y = "",
title = "Citizen sample"
) +
theme_minimal(base_size = 12) +
theme(strip.text.y = element_blank())
fig5_pol_plot
fig5_cit_plot
# 1. Helper: run vignette model with felm
run_vig_felm <- function(data, outcome_var) {
form_text <- paste0(
outcome_var,
" ~ text_pol + text_user + party_pol_copartisan + ",
"woman_pol + gendered + woman_user | country | 0 | id"
)
form <- as.formula(form_text)
felm(form, data = data)
}
# 2. Helper: extract woman-politician coef + CI
extract_woman_pol_felm <- function(model, group_label, sample_label) {
sm <- summary(model)
coef_mat <- sm$coef
row_index <- grep("^woman_pol", rownames(coef_mat))[1]
est <- coef_mat[row_index, "Estimate"]
if ("Cluster s.e." %in% colnames(coef_mat)) {
se <- coef_mat[row_index, "Cluster s.e."]
} else if ("Std. Error" %in% colnames(coef_mat)) {
se <- coef_mat[row_index, "Std. Error"]
} else {
se <- coef_mat[row_index, 2]
}
lower <- est - 1.96 * se
upper <- est + 1.96 * se
data.frame(
group = group_label,
respondent_type = sample_label,
estimate = est,
lower = lower,
upper = upper,
stringsAsFactors = FALSE
)
}
# 3. Run models for the 7 motivations
# Labels based on figure given in the paper
motivation_labels <- c(
prejudice = "Motivated by prejudice",
discourage_pol = "To discourage politician from being in politics",
opinion_diff = "Opinion difference with politician",
dislike_party = "Dislike of the politician's party",
dissatisfied = "Dissatisfaction with own life",
troll_pol = "To get a reaction from the politician",
troll_user = "To get a reaction from other users"
)
fig6_rows <- list()
for (mot in names(motivation_labels)) {
label <- motivation_labels[[mot]]
# politician
mod_pol <- run_vig_felm(data = vig_pol,outcome_var = mot)
temp_pol <- extract_woman_pol_felm( model = mod_pol, group_label = label, sample_label = "Politician sample")
fig6_rows[[length(fig6_rows) + 1]] <- temp_pol
# citizen
mod_cit <- run_vig_felm(data = vig_cit,outcome_var = mot)
temp_cit <- extract_woman_pol_felm(model = mod_cit, group_label = label, sample_label= "Citizen sample")
fig6_rows[[length(fig6_rows) + 1]] <- temp_cit
}
## 4. make df
fig6 <- rbind(
fig6_rows[[1]], fig6_rows[[2]], fig6_rows[[3]], fig6_rows[[4]],
fig6_rows[[5]], fig6_rows[[6]], fig6_rows[[7]], fig6_rows[[8]],
fig6_rows[[9]], fig6_rows[[10]], fig6_rows[[11]], fig6_rows[[12]],
fig6_rows[[13]], fig6_rows[[14]]
)
fig6$group <- factor( fig6$group, levels = rev(c(
"Motivated by prejudice",
"To discourage politician from being in politics",
"Opinion difference with politician",
"Dislike of the politician's party",
"Dissatisfaction with own life",
"To get a reaction from the politician",
"To get a reaction from other users"
))
)
fig6$respondent_type <- factor(fig6$respondent_type, levels = c("Politician sample", "Citizen sample"))
# 5. Plot
fig6_plot <- ggplot(fig6,
aes(x = estimate, y = group,
colour = respondent_type)) +
geom_vline(xintercept = 0) +
geom_point(size = 2.5) +
geom_errorbarh(aes(xmin = lower, xmax = upper), height = 0) +
facet_wrap(~ respondent_type) +
coord_cartesian(xlim = c(-0.15, 0.35)) +
scale_x_continuous(
breaks = seq(-0.1, 0.3, by = 0.1),
labels = c("-0.1", "0", "0.1", "0.2", "0.3")
) +
scale_colour_manual(
values = c("Politician sample" = "#FF3E00",
"Citizen sample" = "#5200FF")
) +
labs(
x = "Coefficient",
y = NULL
) +
theme_minimal(base_size = 12) +
theme(
legend.position = "none",
strip.text.x = element_text(face = "bold")
)
fig6_plot
# Helper: coef + 95% CI for one term from a felm()
get_ci <- function(model, term_name) {
sm <- summary(model, robust = TRUE)
coefs <- sm$coefficients
rn <- rownames(coefs)
idx <- which(rn == term_name)
if (length(idx) != 1L) stop(paste("Term not found or not unique:", term_name))
est <- coefs[idx, "Estimate"]
if ("Cluster s.e." %in% colnames(coefs)) {
se <- coefs[idx, "Cluster s.e."]
} else {
se <- coefs[idx, "Std. Error"]
}
z <- qnorm(0.975)
lower <- est - z * se
upper <- est + z * se
c(estimate = est, lower = lower, upper = upper, se = se)
}
# 7A: woman politician × gendered text
mod7A_pol <- felm(
prejudice ~ text_pol + text_user + party_pol_copartisan +
woman_pol * gendered + woman_user + woman_pol |
country | 0 | id,
data = subset(vig, respondent_type == "Politician")
)
mod7A_cit <- felm(
prejudice ~ text_pol + text_user + party_pol_copartisan +
woman_pol * gendered + woman_user + woman_pol |
country | 0 | id,
data = subset(vig, respondent_type == "Citizen")
)
fig7A <- data.frame()
# interaction: Woman politician x gendered text
ci <- get_ci(mod7A_pol, "woman_polWoman politician:genderedGendered text")
temp <- data.frame(
estimate = ci["estimate"],
lower = ci["lower"],
upper = ci["upper"],
std.error = ci["se"],
feature = "Interaction",
level = "Woman politician x gendered text",
sample = "Politician sample",
stringsAsFactors = FALSE
)
fig7A <- rbind(fig7A, temp)
ci <- get_ci(mod7A_cit, "woman_polWoman politician:genderedGendered text")
temp <- data.frame(
estimate = ci["estimate"],
lower = ci["lower"],
upper = ci["upper"],
std.error = ci["se"],
feature = "Interaction",
level = "Woman politician x gendered text",
sample = "Citizen sample",
stringsAsFactors = FALSE
)
fig7A <- rbind(fig7A, temp)
# main effect: gender of politician
ci <- get_ci(mod7A_pol, "woman_polWoman politician")
temp <- data.frame(
estimate = ci["estimate"],
lower = ci["lower"],
upper = ci["upper"],
std.error = ci["se"],
feature = "Gender of politician",
level = "Woman politician",
sample = "Politician sample",
stringsAsFactors = FALSE
)
fig7A <- rbind(fig7A, temp)
ci <- get_ci(mod7A_cit, "woman_polWoman politician")
temp <- data.frame(
estimate = ci["estimate"],
lower = ci["lower"],
upper = ci["upper"],
std.error = ci["se"],
feature = "Gender of politician",
level = "Woman politician",
sample = "Citizen sample",
stringsAsFactors = FALSE
)
fig7A <- rbind(fig7A, temp)
# main effect: Gendered text
ci <- get_ci(mod7A_pol, "genderedGendered text")
temp <- data.frame(
estimate = ci["estimate"],
lower = ci["lower"],
upper = ci["upper"],
std.error = ci["se"],
feature = "Gendered text",
level = "Gendered text",
sample = "Politician sample",
stringsAsFactors = FALSE
)
fig7A <- rbind(fig7A, temp)
ci <- get_ci(mod7A_cit, "genderedGendered text")
temp <- data.frame(
estimate = ci["estimate"],
lower = ci["lower"],
upper = ci["upper"],
std.error = ci["se"],
feature = "Gendered text",
level = "Gendered text",
sample = "Citizen sample",
stringsAsFactors = FALSE
)
fig7A <- rbind(fig7A, temp)
baseline7A <- data.frame(
estimate = c(0, 0),
lower = c(NA, NA),
upper = c(NA, NA),
std.error = c(NA, NA),
feature = c("Gender of politician", "Gendered text"),
level = c("Man politician", "Non-gendered text"),
sample = c("Baseline", "Baseline"),
stringsAsFactors = FALSE
)
fig7A <- rbind(fig7A, baseline7A)
fig7A$sample <- factor(fig7A$sample,
levels = c("Politician sample", "Citizen sample", "Baseline"))
# 7B: woman politician × man user
mod7B_pol <- felm(
prejudice ~ text_pol + text_user + party_pol_copartisan +
woman_pol * woman_user + woman_user + woman_pol |
country | 0 | id,
data = subset(vig, respondent_type == "Politician")
)
mod7B_cit <- felm(
prejudice ~ text_pol + text_user + party_pol_copartisan +
woman_pol * woman_user + woman_user + woman_pol |
country | 0 | id,
data = subset(vig, respondent_type == "Citizen")
)
fig7B <- data.frame()
# interaction: Woman politician x man user
ci <- get_ci(mod7B_pol, "woman_polWoman politician:woman_userMan user")
temp <- data.frame(
estimate = ci["estimate"],
lower = ci["lower"],
upper = ci["upper"],
std.error = ci["se"],
feature = "Interaction",
level = "Woman politician x man user",
sample = "Politician sample",
stringsAsFactors = FALSE
)
fig7B <- rbind(fig7B, temp)
ci <- get_ci(mod7B_cit, "woman_polWoman politician:woman_userMan user")
temp <- data.frame(
estimate = ci["estimate"],
lower = ci["lower"],
upper = ci["upper"],
std.error = ci["se"],
feature = "Interaction",
level = "Woman politician x man user",
sample = "Citizen sample",
stringsAsFactors = FALSE
)
fig7B <- rbind(fig7B, temp)
# main effect: Gender of politician
ci <- get_ci(mod7B_pol, "woman_polWoman politician")
temp <- data.frame(
estimate = ci["estimate"],
lower = ci["lower"],
upper = ci["upper"],
std.error = ci["se"],
feature = "Gender of politician",
level = "Woman politician",
sample = "Politician sample",
stringsAsFactors = FALSE
)
fig7B <- rbind(fig7B, temp)
ci <- get_ci(mod7B_cit, "woman_polWoman politician")
temp <- data.frame(
estimate = ci["estimate"],
lower = ci["lower"],
upper = ci["upper"],
std.error = ci["se"],
feature = "Gender of politician",
level = "Woman politician",
sample = "Citizen sample",
stringsAsFactors = FALSE
)
fig7B <- rbind(fig7B, temp)
# main effect: Gender of user
ci <- get_ci(mod7B_pol, "woman_userMan user")
temp <- data.frame(
estimate = ci["estimate"],
lower = ci["lower"],
upper = ci["upper"],
std.error = ci["se"],
feature = "Gender of user",
level = "Man user",
sample = "Politician sample",
stringsAsFactors = FALSE
)
fig7B <- rbind(fig7B, temp)
ci <- get_ci(mod7B_cit, "woman_userMan user")
temp <- data.frame(
estimate = ci["estimate"],
lower = ci["lower"],
upper = ci["upper"],
std.error = ci["se"],
feature = "Gender of user",
level = "Man user",
sample = "Citizen sample",
stringsAsFactors = FALSE
)
fig7B <- rbind(fig7B, temp)
# baselines for 7B
baseline7B <- data.frame(
estimate = c(0, 0),
lower = c(NA, NA),
upper = c(NA, NA),
std.error = c(NA, NA),
feature = c("Gender of politician", "Gender of user"),
level = c("Man politician", "Woman user"),
sample = c("Baseline", "Baseline"),
stringsAsFactors = FALSE
)
fig7B <- rbind(fig7B, baseline7B)
fig7B$sample <- factor(fig7B$sample,
levels = c("Politician sample", "Citizen sample", "Baseline"))
plot_fig7_interaction <- function(df, feature_name, y_label, main_title) {
panel <- subset(df, feature == feature_name & !is.na(std.error))
panel$level <- factor(panel$level)
ggplot(panel,
aes(x = estimate, y = level, colour = sample)) +
geom_vline(xintercept = 0) +
geom_point(size = 2.5,
position = position_dodge(width = 0.4)) +
geom_errorbarh(aes(xmin = lower, xmax = upper),
height = 0,
position = position_dodge(width = 0.4)) +
scale_x_continuous(
breaks = seq(-0.2, 0.5, by = 0.1),
labels = c("-.2", "-.1", "0", ".1", ".2", ".3", ".4", ".5")
) +
coord_cartesian(xlim = c(-0.2, 0.5)) +
labs(
x = "Coefficient",
y = y_label,
title = main_title
) +
theme_minimal(base_size = 13) +
theme(legend.position = "top")
}
plot_fig7_main <- function(df, feature_name, y_levels, y_label, main_title) {
panel <- subset(df, feature == feature_name)
panel$level <- factor(panel$level, levels = y_levels)
baseline <- subset(panel, is.na(std.error))
by_sample <- subset(panel, !is.na(std.error))
ggplot() +
geom_vline(xintercept = 0) +
geom_point(data = by_sample,
aes(x = estimate, y = level, colour = sample),
size = 2.5,
position = position_dodge(width = 0.4)) +
geom_errorbarh(data = by_sample,
aes(xmin = lower, xmax = upper, y = level, colour = sample),
height = 0,
position = position_dodge(width = 0.4)) +
geom_point(data = baseline,
aes(x = estimate, y = level),
shape = 16, colour = "black", size = 2.5) +
scale_x_continuous(
breaks = seq(-0.2, 0.5, by = 0.1),
labels = c("-.2", "-.1", "0", ".1", ".2", ".3", ".4", ".5")
) +
coord_cartesian(xlim = c(-0.2, 0.5)) +
scale_y_discrete(limits = y_levels, drop = FALSE) +
labs(
x = "Coefficient",
y = y_label,
title = main_title
) +
theme_minimal(base_size = 13) +
theme(legend.position = "top")
}
# plots
# A: woman politician x gendered text
fig7a_interaction <- plot_fig7_interaction(
df = fig7A,
feature_name = "Interaction",
y_label = "Woman politician x gendered text",
main_title = "Interaction: Politician gender × gendered text"
)
fig7a_polgender <- plot_fig7_main(
df = fig7A,
feature_name = "Gender of politician",
y_levels = c("Man politician", "Woman politician"),
y_label = "Gender of politician",
main_title = "Gender of politician"
)
fig7a_gendered <- plot_fig7_main(
df = fig7A,
feature_name = "Gendered text",
y_levels = c("Non-gendered text", "Gendered text"),
y_label = "Gendered text",
main_title = "Gendered text"
)
# B: woman politician x man user
fig7b_interaction <- plot_fig7_interaction(
df = fig7B,
feature_name = "Interaction",
y_label = "Woman politician x man user",
main_title = "Interaction: Politician gender × user gender"
)
fig7b_polgender <- plot_fig7_main(
df = fig7B,
feature_name = "Gender of politician",
y_levels = c("Man politician", "Woman politician"),
y_label = "Gender of politician",
main_title = "Gender of politician"
)
fig7b_usergender <- plot_fig7_main(
df = fig7B,
feature_name = "Gender of user",
y_levels = c("Woman user", "Man user"),
y_label = "Gender of user",
main_title = "Gender of user"
)
fig7a_interaction; fig7a_polgender; fig7a_gendered
fig7b_interaction; fig7b_polgender; fig7b_usergender
library(sandwich)
library(lmtest)
# 1. Original LPM (baseline AMCEs)
lpm_model <- lm(cj_formula, data = data)
# Cluster-robust SEs by respondent (id = respondent identifier)
vcov_lpm_cluster <- vcovCL(lpm_model, cluster = ~ id)
summary_lpm <- coeftest(lpm_model, vcov. = vcov_lpm_cluster)
summary_lpm
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.43933074 0.01116637 39.3441 < 2.2e-16 ***
## text_polPolText02 0.00437634 0.01152442 0.3797 0.7041359
## text_polPolText03 0.01341268 0.01159157 1.1571 0.2472326
## text_polPolText04 0.01339311 0.01158184 1.1564 0.2475261
## text_polPolText05 0.03598143 0.01167846 3.0810 0.0020638 **
## text_polPolText06 0.02191279 0.01146466 1.9113 0.0559657 .
## text_polPolText07 0.02291110 0.01162186 1.9714 0.0486843 *
## text_polPolText08 0.02100116 0.01172156 1.7917 0.0731900 .
## text_polPolText09 0.01191254 0.01159000 1.0278 0.3040335
## text_polPolText10 0.00718687 0.01164173 0.6173 0.5370146
## text_polPolText11 0.00754466 0.01172105 0.6437 0.5197822
## text_polPolText12 0.01558060 0.01164875 1.3375 0.1810525
## text_polPolText13 0.02246017 0.01163637 1.9302 0.0535897 .
## text_polPolText14 0.02932963 0.01165266 2.5170 0.0118383 *
## text_polPolText15 0.01136193 0.01148011 0.9897 0.3223216
## text_polPolText16 0.01995472 0.01140151 1.7502 0.0800912 .
## text_polPolText17 0.01850446 0.01181037 1.5668 0.1171662
## text_polPolText18 0.01705913 0.01158307 1.4728 0.1408188
## text_polPolText19 0.00825457 0.01156716 0.7136 0.4754634
## text_polPolText20 0.01401783 0.01163251 1.2051 0.2281855
## text_userUserText02 -0.04765184 0.01048933 -4.5429 5.558e-06 ***
## text_userUserText03 0.05729123 0.01064073 5.3841 7.302e-08 ***
## text_userUserText04 0.03400212 0.01074014 3.1659 0.0015467 **
## text_userUserText05 -0.11905930 0.01060319 -11.2286 < 2.2e-16 ***
## text_userUserText06 0.00168817 0.01075011 0.1570 0.8752156
## text_userUserText07 -0.11040585 0.01061900 -10.3970 < 2.2e-16 ***
## text_userUserText08 -0.00541292 0.01087970 -0.4975 0.6188205
## text_userUserText09 -0.09515705 0.01065987 -8.9267 < 2.2e-16 ***
## text_userUserText10 0.01486436 0.01071236 1.3876 0.1652664
## text_userUserText11 0.00039408 0.01086786 0.0363 0.9710744
## text_userUserText12 -0.17207339 0.01054474 -16.3184 < 2.2e-16 ***
## text_userUserText13 0.01839457 0.01071552 1.7166 0.0860513 .
## text_userUserText14 0.02377557 0.01084551 2.1922 0.0283679 *
## text_userUserText15 0.11554113 0.01039994 11.1098 < 2.2e-16 ***
## text_userUserText16 -0.01503253 0.01090655 -1.3783 0.1681140
## party_pol_copartisanCo-partisan 0.00414877 0.00440031 0.9428 0.3457673
## woman_userMan user 0.01260403 0.00368475 3.4206 0.0006252 ***
## woman_polWoman politician 0.05209800 0.00370790 14.0506 < 2.2e-16 ***
## genderedGendered text 0.06118113 0.00374031 16.3572 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# 2. Logistic regression + clustered SEs
logit_model <- glm(
cj_formula,
data = data,
family = binomial(link = "logit")
)
vcov_logit_cluster <- vcovCL(logit_model, cluster = ~ id)
summary_logit <- coeftest(logit_model, vcov. = vcov_logit_cluster)
summary_logit
##
## z test of coefficients:
##
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -0.2505017 0.0455622 -5.4980 3.841e-08 ***
## text_polPolText02 0.0181284 0.0473834 0.3826 0.7020248
## text_polPolText03 0.0551924 0.0476951 1.1572 0.2471932
## text_polPolText04 0.0552433 0.0476269 1.1599 0.2460821
## text_polPolText05 0.1480795 0.0480765 3.0801 0.0020694 **
## text_polPolText06 0.0902087 0.0471290 1.9141 0.0556100 .
## text_polPolText07 0.0941668 0.0477683 1.9713 0.0486870 *
## text_polPolText08 0.0864184 0.0482001 1.7929 0.0729876 .
## text_polPolText09 0.0490306 0.0476736 1.0285 0.3037306
## text_polPolText10 0.0295895 0.0478798 0.6180 0.5365781
## text_polPolText11 0.0311189 0.0482145 0.6454 0.5186507
## text_polPolText12 0.0641486 0.0478886 1.3395 0.1803956
## text_polPolText13 0.0924745 0.0478533 1.9325 0.0533032 .
## text_polPolText14 0.1206896 0.0479182 2.5187 0.0117802 *
## text_polPolText15 0.0467877 0.0471950 0.9914 0.3215048
## text_polPolText16 0.0821955 0.0468995 1.7526 0.0796729 .
## text_polPolText17 0.0760772 0.0485589 1.5667 0.1171844
## text_polPolText18 0.0700657 0.0476490 1.4705 0.1414383
## text_polPolText19 0.0340321 0.0475616 0.7155 0.4742773
## text_polPolText20 0.0578516 0.0478184 1.2098 0.2263481
## text_userUserText02 -0.1922450 0.0423456 -4.5399 5.628e-06 ***
## text_userUserText03 0.2331393 0.0433802 5.3743 7.687e-08 ***
## text_userUserText04 0.1376503 0.0435364 3.1617 0.0015684 **
## text_userUserText05 -0.4853072 0.0436144 -11.1272 < 2.2e-16 ***
## text_userUserText06 0.0067480 0.0433596 0.1556 0.8763257
## text_userUserText07 -0.4490739 0.0435441 -10.3131 < 2.2e-16 ***
## text_userUserText08 -0.0219442 0.0438674 -0.5002 0.6169072
## text_userUserText09 -0.3858433 0.0434744 -8.8752 < 2.2e-16 ***
## text_userUserText10 0.0600034 0.0432690 1.3868 0.1655178
## text_userUserText11 0.0015525 0.0438317 0.0354 0.9717444
## text_userUserText12 -0.7142034 0.0446754 -15.9865 < 2.2e-16 ***
## text_userUserText13 0.0743130 0.0433094 1.7159 0.0861872 .
## text_userUserText14 0.0960507 0.0438674 2.1896 0.0285556 *
## text_userUserText15 0.4788454 0.0435052 11.0066 < 2.2e-16 ***
## text_userUserText16 -0.0606564 0.0439602 -1.3798 0.1676467
## party_pol_copartisanCo-partisan 0.0170250 0.0180982 0.9407 0.3468582
## woman_userMan user 0.0518271 0.0151490 3.4211 0.0006236 ***
## woman_polWoman politician 0.2138494 0.0152480 14.0247 < 2.2e-16 ***
## genderedGendered text 0.2509599 0.0153816 16.3156 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# 3. Turn logit coefficients into odds ratios
logit_coef <- summary_logit
logit_results <- data.frame(
term = rownames(logit_coef),
estimate = logit_coef[, "Estimate"],
se = logit_coef[, "Std. Error"],
z = logit_coef[, "z value"],
p = logit_coef[, "Pr(>|z|)"],
OR = exp(logit_coef[, "Estimate"]),
OR_low = exp(logit_coef[, "Estimate"] - 1.96 * logit_coef[, "Std. Error"]),
OR_high = exp(logit_coef[, "Estimate"] + 1.96 * logit_coef[, "Std. Error"])
)
logit_results
## term estimate
## (Intercept) (Intercept) -0.250501689
## text_polPolText02 text_polPolText02 0.018128368
## text_polPolText03 text_polPolText03 0.055192424
## text_polPolText04 text_polPolText04 0.055243340
## text_polPolText05 text_polPolText05 0.148079547
## text_polPolText06 text_polPolText06 0.090208740
## text_polPolText07 text_polPolText07 0.094166755
## text_polPolText08 text_polPolText08 0.086418405
## text_polPolText09 text_polPolText09 0.049030635
## text_polPolText10 text_polPolText10 0.029589539
## text_polPolText11 text_polPolText11 0.031118947
## text_polPolText12 text_polPolText12 0.064148630
## text_polPolText13 text_polPolText13 0.092474451
## text_polPolText14 text_polPolText14 0.120689605
## text_polPolText15 text_polPolText15 0.046787713
## text_polPolText16 text_polPolText16 0.082195544
## text_polPolText17 text_polPolText17 0.076077243
## text_polPolText18 text_polPolText18 0.070065742
## text_polPolText19 text_polPolText19 0.034032078
## text_polPolText20 text_polPolText20 0.057851616
## text_userUserText02 text_userUserText02 -0.192245036
## text_userUserText03 text_userUserText03 0.233139330
## text_userUserText04 text_userUserText04 0.137650257
## text_userUserText05 text_userUserText05 -0.485307164
## text_userUserText06 text_userUserText06 0.006747992
## text_userUserText07 text_userUserText07 -0.449073874
## text_userUserText08 text_userUserText08 -0.021944170
## text_userUserText09 text_userUserText09 -0.385843264
## text_userUserText10 text_userUserText10 0.060003377
## text_userUserText11 text_userUserText11 0.001552541
## text_userUserText12 text_userUserText12 -0.714203443
## text_userUserText13 text_userUserText13 0.074312996
## text_userUserText14 text_userUserText14 0.096050655
## text_userUserText15 text_userUserText15 0.478845446
## text_userUserText16 text_userUserText16 -0.060656439
## party_pol_copartisanCo-partisan party_pol_copartisanCo-partisan 0.017025006
## woman_userMan user woman_userMan user 0.051827057
## woman_polWoman politician woman_polWoman politician 0.213849383
## genderedGendered text genderedGendered text 0.250959941
## se z p OR
## (Intercept) 0.04556218 -5.49801794 3.840839e-08 0.7784102
## text_polPolText02 0.04738344 0.38258869 7.020248e-01 1.0182937
## text_polPolText03 0.04769506 1.15719365 2.471932e-01 1.0567439
## text_polPolText04 0.04762693 1.15991813 2.460821e-01 1.0567977
## text_polPolText05 0.04807647 3.08008356 2.069425e-03 1.1596051
## text_polPolText06 0.04712905 1.91407947 5.561000e-02 1.0944027
## text_polPolText07 0.04776831 1.97132283 4.868696e-02 1.0987430
## text_polPolText08 0.04820013 1.79290807 7.298762e-02 1.0902624
## text_polPolText09 0.04767355 1.02846615 3.037306e-01 1.0502525
## text_polPolText10 0.04787984 0.61799577 5.365781e-01 1.0300317
## text_polPolText11 0.04821453 0.64542670 5.186507e-01 1.0316082
## text_polPolText12 0.04788862 1.33953803 1.803956e-01 1.0662509
## text_polPolText13 0.04785332 1.93245651 5.330318e-02 1.0968851
## text_polPolText14 0.04791816 2.51866094 1.178020e-02 1.1282746
## text_polPolText15 0.04719499 0.99137026 3.215048e-01 1.0478995
## text_polPolText16 0.04689955 1.75258707 7.967291e-02 1.0856681
## text_polPolText17 0.04855885 1.56670176 1.171844e-01 1.0790459
## text_polPolText18 0.04764899 1.47045600 1.414383e-01 1.0725787
## text_polPolText19 0.04756159 0.71553696 4.742773e-01 1.0346178
## text_polPolText20 0.04781838 1.20981955 2.263481e-01 1.0595578
## text_userUserText02 0.04234560 -4.53990634 5.627922e-06 0.8251047
## text_userUserText03 0.04338024 5.37432140 7.687163e-08 1.2625574
## text_userUserText04 0.04353642 3.16172631 1.568369e-03 1.1475741
## text_userUserText05 0.04361439 -11.12722620 9.246826e-29 0.6155081
## text_userUserText06 0.04335956 0.15562869 8.763257e-01 1.0067708
## text_userUserText07 0.04354407 -10.31308986 6.149189e-25 0.6382189
## text_userUserText08 0.04386742 -0.50023841 6.169072e-01 0.9782949
## text_userUserText09 0.04347444 -8.87517529 6.982336e-19 0.6798771
## text_userUserText10 0.04326904 1.38675074 1.655178e-01 1.0618401
## text_userUserText11 0.04383173 0.03542049 9.717444e-01 1.0015537
## text_userUserText12 0.04467544 -15.98648750 1.587322e-57 0.4895819
## text_userUserText13 0.04330940 1.71586279 8.618716e-02 1.0771439
## text_userUserText14 0.04386741 2.18956753 2.855562e-02 1.1008148
## text_userUserText15 0.04350525 11.00661354 3.551015e-28 1.6142096
## text_userUserText16 0.04396015 -1.37980498 1.676467e-01 0.9411465
## party_pol_copartisanCo-partisan 0.01809821 0.94070084 3.468582e-01 1.0171708
## woman_userMan user 0.01514903 3.42114781 6.235743e-04 1.0531936
## woman_polWoman politician 0.01524804 14.02471135 1.100590e-44 1.2384361
## genderedGendered text 0.01538160 16.31559527 7.645722e-60 1.2852586
## OR_low OR_high
## (Intercept) 0.7119102 0.8511220
## text_polPolText02 0.9279818 1.1173948
## text_polPolText03 0.9624339 1.1602955
## text_polPolText04 0.9626114 1.1601997
## text_polPolText05 1.0553259 1.2741884
## text_polPolText06 0.9978381 1.2003122
## text_polPolText07 1.0005410 1.2065833
## text_polPolText08 0.9919785 1.1982842
## text_polPolText09 0.9565621 1.1531194
## text_polPolText10 0.9377659 1.1313754
## text_polPolText11 0.9385853 1.1338506
## text_polPolText12 0.9707240 1.1711783
## text_polPolText13 0.9986828 1.2047438
## text_polPolText14 1.0271315 1.2393775
## text_polPolText15 0.9553147 1.1494573
## text_polPolText16 0.9903196 1.1901968
## text_polPolText17 0.9810831 1.1867905
## text_polPolText18 0.9769437 1.1775756
## text_polPolText19 0.9425289 1.1357041
## text_polPolText20 0.9647634 1.1636663
## text_userUserText02 0.7593880 0.8965084
## text_userUserText03 1.1596452 1.3746025
## text_userUserText04 1.0537117 1.2497976
## text_userUserText05 0.5650781 0.6704387
## text_userUserText06 0.9247455 1.0960718
## text_userUserText07 0.5860089 0.6950806
## text_userUserText08 0.8976955 1.0661308
## text_userUserText09 0.6243444 0.7403492
## text_userUserText10 0.9755011 1.1558208
## text_userUserText11 0.9191025 1.0914016
## text_userUserText12 0.4485356 0.5343845
## text_userUserText13 0.9894823 1.1725718
## text_userUserText14 1.0101214 1.1996511
## text_userUserText15 1.4822707 1.7578926
## text_userUserText16 0.8634508 1.0258335
## party_pol_copartisanCo-partisan 0.9817216 1.0538999
## woman_userMan user 1.0223818 1.0849340
## woman_polWoman politician 1.2019716 1.2760068
## genderedGendered text 1.2470890 1.3245965
library(ggplot2)
plot_data <- subset(logit_results, term != "(Intercept)")
# order terms
plot_data$term <- factor(plot_data$term, levels = rev(plot_data$term))
ggplot(plot_data, aes(x = estimate, y = term)) +
geom_vline(xintercept = 0, linetype = "dashed") +
geom_point() +
geom_errorbar(aes(
xmin = estimate - 1.96 * se,
xmax = estimate + 1.96 * se
),
width = 0
) +
labs(
x = "Logit coefficient (log-odds, 95% CI)",
y = "",
title = "Clustered logit estimates for conjoint attributes"
) +
theme_minimal()
plot_data$term <- factor(plot_data$term, levels = rev(plot_data$term))
ggplot(plot_data, aes(x = OR, y = term)) +
geom_vline(xintercept = 1, linetype = "dashed") +
geom_point() +
geom_errorbar(aes(xmin = OR_low, xmax = OR_high), width = 0) +
labs(
x = "Odds ratio (95% CI)",
y = "",
title = "Odds ratios from clustered logit model"
) +
theme_minimal()