library(ggfixest)
##
# Author note: The examples that follow deliberately follow the original
# examples from the coefplot/iplot help pages. A few "gg-" specific
# features are sprinkled within, with the final set of examples in
# particular highlighting unique features of this package.
#
# Example 1: Basic use and stacking two sets of results on the same graph
#
# Estimation on Iris data with one fixed-effect (Species)
est = feols(Petal.Length ~ Petal.Width + Sepal.Length + Sepal.Width | Species, iris)
ggcoefplot(est)
# Show multiple CIs
ggcoefplot(est, ci_level = c(0.8, 0.95))
# By default, fixest model standard errors are clustered by the first fixed
# effect (here: Species).
# But we can easily switch to "regular" standard-errors
est_std = summary(est, se = "iid")
# You can plot both results at once in the same plot frame...
ggcoefplot(list("Clustered" = est, "IID" = est_std))
# ... or as separate facets
ggcoefplot(list("Clustered" = est, "IID" = est_std), multi_style = "facet") +
theme(legend.position = "none")
#
# Example 2: Interactions
#
# Now we estimate and plot the "yearly" treatment effects
data(base_did)
base_inter = base_did
# We interact the variable 'period' with the variable 'treat'
est_did = feols(y ~ x1 + i(period, treat, 5) | id + period, base_inter)
# In the estimation, the variable treat is interacted
# with each value of period but 5, set as a reference
# ggcoefplot will show all the coefficients:
ggcoefplot(est_did)
# Note that the grouping of the coefficients is due to 'group = "auto"'
# If you want to keep only the coefficients
# created with i() (ie the interactions), use ggiplot
ggiplot(est_did)
# We can see that the graph is different from before:
# - only interactions are shown,
# - the reference is present,
# => this is fully flexible
ggiplot(est_did, ci_level = c(0.8, 0.95))
ggiplot(est_did, ref.line = FALSE, pt.join = TRUE, geom_style = "errorbar")
ggiplot(est_did, geom_style = "ribbon", col = "orange")
# etc
# We can also use a dictionary to replace label values. The dicionary should
# take the form of a named vector or list, e.g. c("old_lab1" = "new_lab1", ...)
# Let's create a "month" variable
all_months = c("aug", "sept", "oct", "nov", "dec", "jan",
"feb", "mar", "apr", "may", "jun", "jul")
# Turn into a dictionary by providing the old names
# Note the implication that treatment occured here in December (5 month in our series)
dict = all_months; names(dict) = 1:12
# Pass our new dictionary to our ggiplot call
ggiplot(est_did, pt.join = TRUE, geom_style = "errorbar", dict = dict)
#
# What if the interacted variable is not numeric?
# let's re-use our all_months vector from the previous example, but add it
# directly to the dataset
base_inter$period_month = all_months[base_inter$period]
# The new estimation
est = feols(y ~ x1 + i(period_month, treat, "oct") | id+period, base_inter)
# Since 'period_month' of type character, iplot/coefplot both sort it
ggiplot(est)
# To respect a plotting order, use a factor
base_inter$month_factor = factor(base_inter$period_month, levels = all_months)
est = feols(y ~ x1 + i(month_factor, treat, "oct") | id + period, base_inter)
ggiplot(est)
# dict -> c("old_name" = "new_name")
dict = all_months; names(dict) = 1:12; dict
ggiplot(est_did, dict = dict)
#
# Example 3: Setting defaults
#
# The customization logic of ggcoefplot/ggiplot works differently than the
# original base fixest counterparts, so we don't have "gg" equivalents of
# setFixest_coefplot and setFixest_iplot. However, you can still invoke some
# global fixest settings like setFixest_dict(). SImple example:
base_inter$letter = letters[base_inter$period]
est_letters = feols(y ~ x1 + i(letter, treat, 'e') | id+letter, base_inter)
# Set global dictionary for capitalising the letters
dict = LETTERS[1:10]; names(dict) = letters[1:10]
setFixest_dict(dict)
ggiplot(est_letters)
setFixest_dict() # reset
#
# Example 4: group + cleaning
#
# You can use the argument group to group variables
# You can further use the special character "^^" to clean
# the beginning of the coef. name: particularly useful for factors
est = feols(Petal.Length ~ Petal.Width + Sepal.Length +
Sepal.Width + Species, iris)
# No grouping:
ggcoefplot(est)
# now we group by Sepal and Species
ggcoefplot(est, group = list(Sepal = "Sepal", Species = "Species"))
# now we group + clean the beginning of the names using the special character ^^
ggcoefplot(est, group = list(Sepal = "^^Sepal.", Species = "^^Species"))
#
# Example 5: Some more ggcoefplot/ggiplot extras
#
# We'll demonstrate using the staggered treatment example from the
# introductory fixest vignette.
data(base_stagg)
est_twfe = feols(
y ~ x1 + i(time_to_treatment, treated, ref = c(-1, -1000)) | id + year,
base_stagg
)
est_sa20 = feols(
y ~ x1 + sunab(year_treated, year) | id + year,
data = base_stagg
)
# Plot both regressions in a faceted plot
ggiplot(
list('TWFE' = est_twfe, 'Sun & Abraham (2020)' = est_sa20),
main = 'Staggered treatment', ref.line = -1, pt.join = TRUE
)
# So far that's no different than base iplot (automatic legend aside). But 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 dataset.
base_stagg_grp = base_stagg
base_stagg_grp$grp = ifelse(base_stagg_grp$id %% 2 == 0, 'Evens', 'Odds')
# Now re-run our two regressions from earlier, but splitting the sample to
# generate fixest_multi objects.
est_twfe_grp = feols(
y ~ x1 + i(time_to_treatment, treated, ref = c(-1, -1000)) | id + year,
data = base_stagg_grp, split = ~ grp
)
est_sa20_grp = feols(
y ~ x1 + sunab(year_treated, year) | id + year,
data = base_stagg_grp, split = ~ grp
)
# ggiplot combines the list of multi-estimation objects without a problem...
ggiplot(list('TWFE' = est_twfe_grp, 'Sun & Abraham (2020)' = est_sa20_grp),
ref.line = -1, main = 'Staggered treatment: Split multi-sample')
# ... but is even better when we use facets instead of dodged errorbars.
# Let's use this 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 multi-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'
)
)
#
# Aside on theming and scale adjustments
#
# 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() +
labs(caption = 'Note: Super fancy plot brought to you by ggiplot')
last_plot() +
theme_grey() +
theme(legend.position = 'none') +
scale_fill_brewer(palette = 'Set1', aesthetics = c("colour", "fill"))
# etc.
#' @export
Run the code above in your browser using DataLab