I want to use sprintf to add an annotation to a ggplot in a loop.
att_fig <- ggdid(att, legend=F, x_lab='', ax_text_size = 8, ylab='', title='ATT by year', title_size = 10) +
labs(caption = sprintf('2005 ATT(SE): %.3f (%.3f)\n2010 ATT(SE): %.3f (%.3f)\n2014 ATT(SE): %.3f (%.3f)',
att$att.egt[[1]], att$se.egt[[1]], att$att.egt[[2]], att$se.egt[[2]], att$att.egt[[3]], att$se.egt[[3]]))
Problem is that in some cases, there are only 1 or 2 elements in the att.egt and se.egt vectors.
I tried with a try():
try(
labs(caption = sprintf('2005 ATT(SE): %.3f (%.3f)\n2010 ATT(SE): %.3f (%.3f)\n2014 ATT(SE): %.3f (%.3f)',
att$att.egt[[1]], att$se.egt[[1]], att$att.egt[[2]], att$se.egt[[2]], att$att.egt[[3]], att$se.egt[[3]]))
) +
try(
labs(caption = sprintf('2010 ATT(SE): %.3f (%.3f)\n2014 ATT(SE): %.3f (%.3f)',
att$att.egt[[1]], att$se.egt[[1]], att$att.egt[[2]], att$se.egt[[2]]))
)
But ggplot is unhappy and returns:
Error in att$att.egt[[3]] : subscript out of bounds
Error in `ggplot_add()`:
! Can't add `try(labs(caption = sprintf("2005 ATT(SE): %.3f (%.3f)\n2010 ATT(SE): %.3f (%.3f)\n2014 ATT(SE): %.3f (%.3f)", ` to a ggplot object.
• Can't add ` att$att.egt[[1]], att$se.egt[[1]], att$att.egt[[2]], att$se.egt[[2]], ` to a ggplot object.
• Can't add ` att$att.egt[[3]], att$se.egt[[3]])))` to a ggplot object.
Traceback:
1. `+.gg`(ggdid(att, legend = F, x_lab = "", ax_text_size = 8, ylab = "",
. title = "ATT by year", title_size = 10), try(labs(caption = sprintf("2005 ATT(SE): %.3f (%.3f)\n2010 ATT(SE): %.3f (%.3f)\n2014 ATT(SE): %.3f (%.3f)",
. att$att.egt[[1]], att$se.egt[[1]], att$att.egt[[2]], att$se.egt[[2]],
. att$att.egt[[3]], att$se.egt[[3]]))))
2. add_ggplot(e1, e2, e2name)
3. ggplot_add(object, p, objectname)
4. ggplot_add.default(object, p, objectname)
5. abort(glue("Can't add `{object_name}` to a ggplot object."))
6. signal_abort(cnd, .file)
Any idea how I could proceed?
Edit: Here is the full code but the problem should be pretty obvious without it:
parties <- c('Union', 'SPD', 'FDP', 'Linke', 'Grüne', 'Andere')
treatments <- hash('treatment_0'='Direct Line', 'treatment_15'='Within 15km', 'treatment_30'='Within 30km', 'treatment_50'='Within 50km')
keys <- keys(treatments)
results <- list()
for(party in parties){
figures <- list()
for(treatment in keys){
result <- att_gt(yname = party,
gname = treatment,
idname = 'AGS',
panel = TRUE,
tname = 'year',
xformla = ~ 1,
data = ltw,
est_method = 'reg',
anticipation = 0,
control_group = 'nevertreated',
clustervars = c('AGS'),
bstrap = TRUE,
cband = TRUE,
allow_unbalanced_panel = TRUE,
)
results[[length(results)+1]] <- result
# calculate ATT
att <- aggte(result, type = "group", bstrap = TRUE, clustervars = c('AGS'))
# plot results
result_fig <- ggdid(result,
ylim = c(floor(min(result$att - result$se * 2.345 - 1)), ceiling(max(result$att + result$se * 2.345 + 1))),
ncol = 3, ax_text_size = 8, grtitle='', title_size = 10, legend=F) +
labs(caption = sprintf('Overall ATT (SE): %.3f (%.3f) \n Wald-P: %.3f \n # Obs.: %s' ,
att$overall.att, att$overall.se, result$Wpval, result$n)) +
theme(plot.caption = element_text(hjust=0.5, size=8),
panel.background = element_rect(fill='transparent'),
plot.background = element_rect(fill='transparent', color=NA),
legend.background = element_rect(fill='transparent'),
legend.box.background = element_rect(fill='transparent'),
plot.margin=unit(c(0,0,0,0),"cm"))
# Plot ATT
att_fig <- ggdid(att, legend=F, x_lab='', ax_text_size = 8, ylab='', title='ATT by year', title_size = 10) +
labs(caption = sprintf('2005 ATT(SE): %.3f (%.3f)\n2010 ATT(SE): %.3f (%.3f)\n2014 ATT(SE): %.3f (%.3f)',
att$att.egt[[1]], att$se.egt[[1]], att$att.egt[[2]], att$se.egt[[2]], att$att.egt[[3]], att$se.egt[[3]])) +
theme(plot.caption = element_text(hjust=0.5, size=8),
axis.title.x = element_blank(),
axis.text.y = element_text(angle=90, size=6, hjust=0.5),
panel.background = element_rect(fill='transparent'),
plot.background = element_rect(fill='transparent', color=NA),
legend.background = element_rect(fill='transparent'),
legend.box.background = element_rect(fill='transparent'),
plot.margin=unit(c(0,0,0,0),"cm"))
# Combine and annotate Group and ATT plot
combined_fig <- ggarrange(result_fig, att_fig, widths = c(3, 1)) +
theme(plot.margin=unit(c(0,0,0,0),"cm"))
combined_fig_anno <- annotate_figure(combined_fig,
top = text_grob(sprintf('%s', treatments[[treatment]])))
figures[[length(figures)+1]] <- combined_fig_anno
}
# Combine Figures for all treatments
arranged_fig <- ggarrange(plotlist=figures, nrow = 4, ncol = 1, common.legend = TRUE)
# get legend
result_fig <- ggdid(result) +
theme(
legend.background = element_rect(fill='transparent', color='transparent'),
legend.box.background = element_rect(fill='transparent', color='transparent'),
plot.margin=unit(c(0,0,0,0),"cm"))
leg <- get_legend(result_fig)
# add legend
arranged_fig_leg <- ggarrange(arranged_fig, leg, nrow = 2, ncol = 1, heights = c(10, 1))
final_fig <- annotate_figure(arranged_fig_leg,
top = text_grob(sprintf("LTW: Effect on %s's vote share", party), face = "bold", size = 14),
bottom = text_grob('Control Group: Never Treated. Estimation Method: Regression \n SE clustered on the municipality level.', size = 10),)
ggsave(sprintf('%s_all.png', party), plot = final_fig, path = sprintf('%s/figures/R/LTW/pooled', path), units = 'cm', width = 21, height = 29.7, dpi="print")
print(party)
}
EDIT 2:
Maybe theres a way to streamline this. ggdid(att) returns among others: att.egt se.egt glist
which look like this:
> dput(att$DIDparams$glist)
c(2005, 2010, 2014)
> dput(att$att.egt)
c(2.62788545990323, 0.335795773304143, 0.644448602052905)
> dput(att$se.egt)
c(0.151836561441285, 0.187353304600586, 0.200190942502885)
Now is there any way to put these together in one string (and add a Group before year) similar to list comprehension in python?
EDIT 3: Solved it
cap = ''
for(i in 1:length(att$DIDparams$glist)) {
cap = sprintf('%s Group %s: ATT(SE) %.3f (%.3f) \n', cap, att$DIDparams$glist[[i]], att$att.egt[[i]], att$se.egt[[i]])
}
print(cap)
>>Group 2005: ATT(SE) 2.628 (0.152) \n Group 2010: ATT(SE) 0.336 (0.187) \n Group 2014: ATT(SE) 0.644 (0.200) \n"