Comparing ggiplot with iplotSource:
As far as possible, ggiplot (
tries to mimic the behaviour of its base compatriot
fixest::iplot). However, by leveraging the
ggplot2 API and infrastructure, it also offers some
additional functionality. This vignette will walk you through the key
differences and correspondences.
Start by loading ggiplot alongside fixest. Note that you always have to load the latter alongside the former if you actually want to run the underlying regressions. (Which, presumably, you do.)
Let’s compare the (base)
There are some small differences, but they are certainly producing
the same basic plot. To get even closer to the original, we could
specify the use of errorbar(s) rather than (
default of) pointrange(s).
ggiplot(est_did, geom = 'errorbar')
Many of the arguments for
iplot() carry over to
ggiplot() too. This is deliberate, since we want to reduce
the cognitive overhead of switching between the two plotting methods.
For example, we can join points using the same
pt.join = TRUE argument.
iplot(est_did, pt.join = TRUE)
ggiplot(est_did, pt.join = TRUE, geom_style = 'errorbar')
ggiplot defaults are slightly different in some
cases, but may require less arguments depending on what you want to do.
ggiplot(est_did, geom_style = 'ribbon')
ggiplot(est_did, geom_style = 'ribbon', pt.pch = NA, col = 'orange') #> Scale for colour is already present. #> Adding another scale for colour, which will replace the existing scale.
iplot, multiple confidence interval levels
are supported. This works for ribbons too.
Another new feature (i.e. unsupported in base
adding aggregated post- and/or pre-treatment effects to your plots.
Here’s an example that builds on the previous plot, by adding the mean
We’ll demonstrate multiple estimation functionality using the staggered treatment example (comparing vanilla TWFE with the Sun-Abraham estimator) from the fixest introductory vignette.
Again, for comparison, here the base
Note that we add the legend manually.
If we don’t name out list of models then it defaults to something sensible.
One nice thing about the ggplot2 API is that it
makes changing multiplot figures simple. For example, if you don’t like
the presentation of “dodged” models in a single frame, then it’s easy to
facet them instead using the
multi_style = 'facet'
An area where
ggiplot shines is in complex multiple
estimation cases, such as lists of
fixest_multi objects. To
illustrate, let’s add a split variable (group) to our staggered
Now re-run our two regressions from earlier, but splitting the sample
ggiplot do fine with a
fixest_multi object (although remember that we have
to manually add a legend for the former)
ggiplot(est_twfe_grp, ref.line = -1, main = 'Staggered treatment: TWFE')
iplot complains if we combine a list of
iplot( list('TWFE' = est_twfe_grp, 'Sun & Abraham (2020)' = est_sa20_grp), ref.line = -1, main = 'Staggered treatment: Split mutli-sample' ) #> The degrees of freedom for the t distribution could not be deduced. Using a Normal distribution instead. #> Note that you can provide the argument `df.t` directly. #> Error in coefplot_prms(object = object, ..., sd = sd, ci_low = ci_low, : The first element of 'object' raises and error: #> Error in nb * sd : non-numeric argument to binary operator
… but is even better when we use faceting instead of dodged errorbars. Let’s use this as an opportunity to construct a fancy plot that invokes some additional arguments and ggplot theming.
ggiplot( list("TWFE" = est_twfe_grp, "Sun & Abraham (2020)" = est_sa20_grp), ref.line = -1, main = "Staggered treatment: Split mutli-sample", xlab = "Time to treatment", multi_style = "facet", geom_style = "ribbon", facet_args = list(labeller = labeller(id = \(x) gsub(".*: ", "", x))), theme = theme_minimal() + theme( text = element_text(family = "HersheySans"), plot.title = element_text(hjust = 0.5), legend.position = "none" ) )
Setting the theme inside the
ggiplot() call is optional
and not strictly necessary, since the ggplot2 API allows programmatic
updating of existing plots. E.g.
last_plot() + theme_grey() + theme(legend.position = 'none') + scale_fill_brewer(palette = 'Set1', aesthetics = c('colour', 'fill')) #> Scale for colour is already present. #> Adding another scale for colour, which will replace the existing scale.
Dictionaries work similarly to
You can either set the dictionary directly in the plot call…
ggiplot(est_letters, dict = dict)
… Or, set it globally using the
setFixest_dict() # reset