From d96aea726715d816775ce42506ee14526226e484 Mon Sep 17 00:00:00 2001 From: Grant McDermott Date: Mon, 11 Dec 2023 16:39:45 -0800 Subject: [PATCH 1/6] Lower tol for tests --- inst/tinytest/test_aggr_es.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inst/tinytest/test_aggr_es.R b/inst/tinytest/test_aggr_es.R index 0c7ab98..ffdeac0 100644 --- a/inst/tinytest/test_aggr_es.R +++ b/inst/tinytest/test_aggr_es.R @@ -80,7 +80,7 @@ aggr_rhs1_known = data.frame( # # tests ---- -tol = 1e-6 +tol = 1e-4 for (col in c("term", "estimate", "std.error", "statistic", "p.value", "s.value", "conf.low", "conf.high")) { From e690ee1c99d29f7969b0cb9671b6b0b3e7cec4de Mon Sep 17 00:00:00 2001 From: Grant McDermott Date: Mon, 11 Dec 2023 16:43:18 -0800 Subject: [PATCH 2/6] Fix URL --- README.Rmd | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.Rmd b/README.Rmd index d05114c..3bbfd8e 100644 --- a/README.Rmd +++ b/README.Rmd @@ -43,7 +43,7 @@ install.packages("ggfixest", repos = "https://grantmcdermott.r-universe.dev") ## Quickstart -The [package website](http://grantmcdermott.com/ggfixest) +The [package website](https://grantmcdermott.com/ggfixest/) provides a number of examples in the help documentation. (Also available by typing `?ggcoefplot` or `?ggiplot` in your R console.) But here are a few quickstart examples to whet your appetite. diff --git a/README.md b/README.md index d1fea20..e060a65 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ install.packages("ggfixest", repos = "https://grantmcdermott.r-universe.dev") ## Quickstart -The [package website](http://grantmcdermott.com/ggfixest) provides a +The [package website](https://grantmcdermott.com/ggfixest/) provides a number of examples in the help documentation. (Also available by typing `?ggcoefplot` or `?ggiplot` in your R console.) But here are a few quickstart examples to whet your appetite. From f837d3c2ead766ab81dc195b617aeface3457c81 Mon Sep 17 00:00:00 2001 From: Grant McDermott Date: Mon, 11 Dec 2023 17:54:14 -0800 Subject: [PATCH 3/6] Pass ... to summary.fixest --- NAMESPACE | 2 ++ R/ggcoefplot.R | 3 +++ R/ggiplot.R | 9 ++++----- R/iplot_data.R | 17 +++++++++++++---- man/ggcoefplot.Rd | 3 +++ man/iplot_data.Rd | 10 ++++++++-- 6 files changed, 33 insertions(+), 11 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 4d73143..d52fb34 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -6,3 +6,5 @@ export(ggiplot) export(iplot_data) import(fixest) import(ggplot2) +importFrom(fixest,coefplot) +importFrom(fixest,iplot) diff --git a/R/ggcoefplot.R b/R/ggcoefplot.R index aab9a7a..39b8a61 100644 --- a/R/ggcoefplot.R +++ b/R/ggcoefplot.R @@ -55,6 +55,9 @@ #' channel. For example, we can make the CI band lighter with #' `ci.fill.par = list(alpha = 0.2)` (the default alpha is 0.3). #' * `dict` a dictionary for overriding coefficient names. +#' * All other `...` arguments are passed to `summary.fixest` before plotting +#' (e.g., for on-the-fly VCOV adjustment) and will be silently ignored if +#' not relevant. #' @details These functions generally try to mimic the functionality and (where #' appropriate) arguments of `fixest::coefplot` and `fixest::iplot` as #' closely as possible. However, by leveraging the ggplot2 API and diff --git a/R/ggiplot.R b/R/ggiplot.R index 1e9dc38..768d8c7 100644 --- a/R/ggiplot.R +++ b/R/ggiplot.R @@ -49,7 +49,6 @@ ggiplot = function( ref.line.par = list(col = "black", lty = 2, lwd = 0.3) if (!is.null(dots[["ref.line.par"]])) ref.line.par = utils::modifyList(ref.line.par, dots[["ref.line.par"]]) - # The next few blocks grab the underlying iplot/coefplot data, contingent on the # object that was passed into the function (i.e. fixest, fixest_multi, or # list) @@ -58,11 +57,11 @@ ggiplot = function( if (inherits(object, c("fixest", "fixest_multi"))) { if (length(ci_level) == 1) { - data = iplot_data_func(object, .ci_level = ci_level, .dict = dict, .aggr_es = aggr_eff, .keep = keep, .drop = drop, .group = group, .i.select = i.select) + data = iplot_data_func(object, .ci_level = ci_level, .dict = dict, .aggr_es = aggr_eff, .keep = keep, .drop = drop, .group = group, .i.select = i.select, ...) } else { data = lapply( ci_level, - function(ci_l) iplot_data_func(object, .ci_level = ci_l, .dict = dict, .aggr_es = aggr_eff, .keep = keep, .drop = drop, .group = group, .i.select = i.select) + function(ci_l) iplot_data_func(object, .ci_level = ci_l, .dict = dict, .aggr_es = aggr_eff, .keep = keep, .drop = drop, .group = group, .i.select = i.select, ...) ) data = do.call("rbind", data) } @@ -82,13 +81,13 @@ ggiplot = function( if (length(ci_level) == 1) { data = lapply( object, iplot_data_func, - .ci_level = ci_level, .dict = dict, .aggr_es = aggr_eff, .group = group, .i.select = i.select + .ci_level = ci_level, .dict = dict, .aggr_es = aggr_eff, .group = group, .i.select = i.select, ... ) } else { data = lapply(ci_level, function(ci_l) { lapply(object, iplot_data_func, .ci_level = ci_l, - .dict = dict, .aggr_es = aggr_eff, .group = group, .i.select = i.select + .dict = dict, .aggr_es = aggr_eff, .group = group, .i.select = i.select, ... ) }) data = do.call(function(...) Map("rbind", ...), data) diff --git a/R/iplot_data.R b/R/iplot_data.R index d7117a0..b4095b1 100644 --- a/R/iplot_data.R +++ b/R/iplot_data.R @@ -42,6 +42,9 @@ #' aggregated mean treatment effects for some subset of the model should be #' added as a column to the returned data frame. Passed to #' `aggr_es(..., aggregation = "mean")`. +#' @param ... Other arguments passed on to `summary.fixest`, e.g. for +#' post-estimation VCOV adjustment. Irrelevant arguments will be silently +#' ignored. #' @details This function is a wrapper around #' `fixest::iplot(..., only.params = TRUE)`, but with various checks and tweaks #' to better facilitate plotting with `ggplot2` and handling of complex object @@ -51,6 +54,7 @@ #' relative x-axis positions, and other aesthetic information needed to draw #' a ggplot2 object. #' @import ggplot2 +#' @importFrom fixest coefplot iplot #' @export #' @examples #' library(fixest) @@ -77,7 +81,8 @@ iplot_data = function( .i.select = 1, # .aggr_es = c("none", "post", "pre", "both"), .aggr_es = NULL, - .group = "auto" + .group = "auto", + ... ) { # .aggr_es = match.arg(.aggr_es) @@ -94,7 +99,10 @@ iplot_data = function( .group = NULL } - p = fixest::coefplot(object, only.params = TRUE, ci_level = .ci_level, dict = .dict, keep = .keep, drop = .drop, internal.only.i = .internal.only.i, i.select = .i.select) + # Catch any args pass through ... to summary.fixest (e.g., vcov adjustments) + object = summary(object, ...) + + p = coefplot(object, only.params = TRUE, ci_level = .ci_level, dict = .dict, keep = .keep, drop = .drop, internal.only.i = .internal.only.i, i.select = .i.select) d = p$prms if (inherits(object, "fixest_multi")) { @@ -423,9 +431,10 @@ coefplot_data = function( .dict = fixest::getFixest_dict(), .internal.only.i = FALSE, .i.select = 1, - .aggr_es = "none" + .aggr_es = "none", + ... ) { - iplot_data(object, .ci_level = .ci_level, .dict = .dict, .keep = .keep, .drop = .drop, .internal.only.i = .internal.only.i, .group = .group) + iplot_data(object, .ci_level = .ci_level, .dict = .dict, .keep = .keep, .drop = .drop, .internal.only.i = .internal.only.i, .group = .group, ...) } diff --git a/man/ggcoefplot.Rd b/man/ggcoefplot.Rd index 23a513b..3c5dc1c 100644 --- a/man/ggcoefplot.Rd +++ b/man/ggcoefplot.Rd @@ -70,6 +70,9 @@ are requested for the default pointrange style). The default value is 0.2. channel. For example, we can make the CI band lighter with \code{ci.fill.par = list(alpha = 0.2)} (the default alpha is 0.3). \item \code{dict} a dictionary for overriding coefficient names. +\item All other \code{...} arguments are passed to \code{summary.fixest} before plotting +(e.g., for on-the-fly VCOV adjustment) and will be silently ignored if +not relevant. }} \item{aggr_eff}{A keyword string or numeric sequence, indicating whether diff --git a/man/iplot_data.Rd b/man/iplot_data.Rd index e967196..d2c2153 100644 --- a/man/iplot_data.Rd +++ b/man/iplot_data.Rd @@ -14,7 +14,8 @@ iplot_data( .internal.only.i = TRUE, .i.select = 1, .aggr_es = NULL, - .group = "auto" + .group = "auto", + ... ) coefplot_data( @@ -26,7 +27,8 @@ coefplot_data( .dict = fixest::getFixest_dict(), .internal.only.i = FALSE, .i.select = 1, - .aggr_es = "none" + .aggr_es = "none", + ... ) } \arguments{ @@ -78,6 +80,10 @@ valid uses: ⁠group=list(group_name=c(\"var_start\", \"var_end\"))⁠, ⁠group=list(group_name=1:2)) See the Details section of \code{?fixest::coefplot} for more.} + +\item{...}{Other arguments passed on to \code{summary.fixest}, e.g. for +post-estimation VCOV adjustment. Irrelevant arguments will be silently +ignored.} } \value{ A data frame consisting of estimate values, confidence intervals, From 48f9e37f0a6f2174f92c7629bfb5113a28962616 Mon Sep 17 00:00:00 2001 From: Grant McDermott Date: Tue, 12 Dec 2023 00:08:16 -0800 Subject: [PATCH 4/6] Rather limit to just vcov and alternatives for safety. --- R/ggcoefplot.R | 7 ++++--- R/ggiplot.R | 32 ++++++++++++++++++++++++++------ R/iplot_data.R | 34 ++++++++++++++++++++++++++-------- man/ggcoefplot.Rd | 7 ++++--- man/iplot_data.Rd | 16 +++++++++++----- 5 files changed, 71 insertions(+), 25 deletions(-) diff --git a/R/ggcoefplot.R b/R/ggcoefplot.R index 39b8a61..b256a7d 100644 --- a/R/ggcoefplot.R +++ b/R/ggcoefplot.R @@ -55,9 +55,10 @@ #' channel. For example, we can make the CI band lighter with #' `ci.fill.par = list(alpha = 0.2)` (the default alpha is 0.3). #' * `dict` a dictionary for overriding coefficient names. -#' * All other `...` arguments are passed to `summary.fixest` before plotting -#' (e.g., for on-the-fly VCOV adjustment) and will be silently ignored if -#' not relevant. +#' * `vcov`, `cluster` or `se` as alternative options for adjusting the +#' standard errors of the model object(s) on the fly. See `summary.fixest` for +#' details. Written here in superseding order; `cluster` will only be +#' considered if `vcov` is not null, etc. #' @details These functions generally try to mimic the functionality and (where #' appropriate) arguments of `fixest::coefplot` and `fixest::iplot` as #' closely as possible. However, by leveraging the ggplot2 API and diff --git a/R/ggiplot.R b/R/ggiplot.R index 768d8c7..73f2216 100644 --- a/R/ggiplot.R +++ b/R/ggiplot.R @@ -49,6 +49,11 @@ ggiplot = function( ref.line.par = list(col = "black", lty = 2, lwd = 0.3) if (!is.null(dots[["ref.line.par"]])) ref.line.par = utils::modifyList(ref.line.par, dots[["ref.line.par"]]) + # VCOV adjustments (if any) + vcov = if (!is.null(dots[['vcov']])) dots[['vcov']] else NULL + cluster = if (!is.null(dots[['cluster']])) dots[['cluster']] else NULL + se = if (!is.null(dots[['se']])) dots[['se']] else NULL + # The next few blocks grab the underlying iplot/coefplot data, contingent on the # object that was passed into the function (i.e. fixest, fixest_multi, or # list) @@ -57,11 +62,21 @@ ggiplot = function( if (inherits(object, c("fixest", "fixest_multi"))) { if (length(ci_level) == 1) { - data = iplot_data_func(object, .ci_level = ci_level, .dict = dict, .aggr_es = aggr_eff, .keep = keep, .drop = drop, .group = group, .i.select = i.select, ...) + data = iplot_data_func( + object, + .ci_level = ci_level, .dict = dict, .aggr_es = aggr_eff, + .keep = keep, .drop = drop, .group = group, .i.select = i.select, + .vcov = vcov, .cluster = cluster, .se = se + ) } else { data = lapply( ci_level, - function(ci_l) iplot_data_func(object, .ci_level = ci_l, .dict = dict, .aggr_es = aggr_eff, .keep = keep, .drop = drop, .group = group, .i.select = i.select, ...) + function(ci_l) iplot_data_func( + object, + .ci_level = ci_l, .dict = dict, .aggr_es = aggr_eff, + .keep = keep, .drop = drop, .group = group, .i.select = i.select, + .vcov = vcov, .cluster = cluster, .se = se + ) ) data = do.call("rbind", data) } @@ -81,13 +96,18 @@ ggiplot = function( if (length(ci_level) == 1) { data = lapply( object, iplot_data_func, - .ci_level = ci_level, .dict = dict, .aggr_es = aggr_eff, .group = group, .i.select = i.select, ... + .ci_level = ci_level, .dict = dict, .aggr_es = aggr_eff, + .group = group, .i.select = i.select, + .vcov = vcov, .cluster = cluster, .se = se ) } else { data = lapply(ci_level, function(ci_l) { - lapply(object, iplot_data_func, - .ci_level = ci_l, - .dict = dict, .aggr_es = aggr_eff, .group = group, .i.select = i.select, ... + lapply( + object, iplot_data_func, + .ci_level = ci_l, + .dict = dict, .aggr_es = aggr_eff, + .group = group, .i.select = i.select, + .vcov = vcov, .cluster = cluster, .se = se ) }) data = do.call(function(...) Map("rbind", ...), data) diff --git a/R/iplot_data.R b/R/iplot_data.R index b4095b1..a04d28a 100644 --- a/R/iplot_data.R +++ b/R/iplot_data.R @@ -42,9 +42,11 @@ #' aggregated mean treatment effects for some subset of the model should be #' added as a column to the returned data frame. Passed to #' `aggr_es(..., aggregation = "mean")`. -#' @param ... Other arguments passed on to `summary.fixest`, e.g. for -#' post-estimation VCOV adjustment. Irrelevant arguments will be silently -#' ignored. +#' @param .vcov,.cluster,.se Alternative options for adjusting the standard +#' errors of the model object on the fly. See `summary.fixest` for details +#' (although note that the "." period prefix should be ignored in the latter's +#' argument documentation). Written here in superseding order; `.cluster` will +#' only be considered if `.vcov` is not null, etc. #' @details This function is a wrapper around #' `fixest::iplot(..., only.params = TRUE)`, but with various checks and tweaks #' to better facilitate plotting with `ggplot2` and handling of complex object @@ -82,7 +84,9 @@ iplot_data = function( # .aggr_es = c("none", "post", "pre", "both"), .aggr_es = NULL, .group = "auto", - ... + .vcov = NULL, + .cluster = NULL, + .se = NULL ) { # .aggr_es = match.arg(.aggr_es) @@ -99,8 +103,14 @@ iplot_data = function( .group = NULL } - # Catch any args pass through ... to summary.fixest (e.g., vcov adjustments) - object = summary(object, ...) + # Catch VCOV adjustments (if any) + if (!is.null(.vcov)) { + object = summary(object, vcov = .vcov) + } else if (!is.null(.cluster)) { + object = summary(object, cluster = .cluster) + } else if (!is.null(.se)) { + object = summary(object, se = .se) + } p = coefplot(object, only.params = TRUE, ci_level = .ci_level, dict = .dict, keep = .keep, drop = .drop, internal.only.i = .internal.only.i, i.select = .i.select) d = p$prms @@ -432,9 +442,17 @@ coefplot_data = function( .internal.only.i = FALSE, .i.select = 1, .aggr_es = "none", - ... + .vcov = NULL, + .cluster = NULL, + .se = NULL ) { - iplot_data(object, .ci_level = .ci_level, .dict = .dict, .keep = .keep, .drop = .drop, .internal.only.i = .internal.only.i, .group = .group, ...) + iplot_data( + object, + .ci_level = .ci_level, .dict = .dict, + .keep = .keep, .drop = .drop, + .internal.only.i = .internal.only.i, .group = .group, + .vcov = .vcov, .cluster = .cluster, .se = .se + ) } diff --git a/man/ggcoefplot.Rd b/man/ggcoefplot.Rd index 3c5dc1c..5009eb7 100644 --- a/man/ggcoefplot.Rd +++ b/man/ggcoefplot.Rd @@ -70,9 +70,10 @@ are requested for the default pointrange style). The default value is 0.2. channel. For example, we can make the CI band lighter with \code{ci.fill.par = list(alpha = 0.2)} (the default alpha is 0.3). \item \code{dict} a dictionary for overriding coefficient names. -\item All other \code{...} arguments are passed to \code{summary.fixest} before plotting -(e.g., for on-the-fly VCOV adjustment) and will be silently ignored if -not relevant. +\item \code{vcov}, \code{cluster} or \code{se} as alternative options for adjusting the +standard errors of the model object(s) on the fly. See \code{summary.fixest} for +details. Written here in superseding order; \code{cluster} will only be +considered if \code{vcov} is not null, etc. }} \item{aggr_eff}{A keyword string or numeric sequence, indicating whether diff --git a/man/iplot_data.Rd b/man/iplot_data.Rd index d2c2153..3e2a6e4 100644 --- a/man/iplot_data.Rd +++ b/man/iplot_data.Rd @@ -15,7 +15,9 @@ iplot_data( .i.select = 1, .aggr_es = NULL, .group = "auto", - ... + .vcov = NULL, + .cluster = NULL, + .se = NULL ) coefplot_data( @@ -28,7 +30,9 @@ coefplot_data( .internal.only.i = FALSE, .i.select = 1, .aggr_es = "none", - ... + .vcov = NULL, + .cluster = NULL, + .se = NULL ) } \arguments{ @@ -81,9 +85,11 @@ valid uses: ⁠group=list(group_name=1:2)) See the Details section of \code{?fixest::coefplot} for more.} -\item{...}{Other arguments passed on to \code{summary.fixest}, e.g. for -post-estimation VCOV adjustment. Irrelevant arguments will be silently -ignored.} +\item{.vcov, .cluster, .se}{Alternative options for adjusting the standard +errors of the model object on the fly. See \code{summary.fixest} for details +(although note that the "." period prefix should be ignored in the latter's +argument documentation). Written here in superseding order; \code{.cluster} will +only be considered if \code{.vcov} is not null, etc.} } \value{ A data frame consisting of estimate values, confidence intervals, From d9e1c8240dd5aba89685ea369acf61f9c1f62344 Mon Sep 17 00:00:00 2001 From: Grant McDermott Date: Tue, 12 Dec 2023 00:08:28 -0800 Subject: [PATCH 5/6] Update tests --- .../_tinysnapshot/ggcoefplot_did_iid.svg | 86 +++++ .../ggiplot_multi_complex_kitchen_iid.svg | 349 ++++++++++++++++++ inst/tinytest/test_ggcoefplot.R | 10 + inst/tinytest/test_ggiplot.R | 38 ++ 4 files changed, 483 insertions(+) create mode 100644 inst/tinytest/_tinysnapshot/ggcoefplot_did_iid.svg create mode 100644 inst/tinytest/_tinysnapshot/ggiplot_multi_complex_kitchen_iid.svg diff --git a/inst/tinytest/_tinysnapshot/ggcoefplot_did_iid.svg b/inst/tinytest/_tinysnapshot/ggcoefplot_did_iid.svg new file mode 100644 index 0000000..6caf367 --- /dev/null +++ b/inst/tinytest/_tinysnapshot/ggcoefplot_did_iid.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +5 + + + + + + + + + + + + +x1 +1 +2 +3 +4 +6 +7 +8 +9 +10 + +treat × (period = ...) +Estimate and 95% Conf. Int. +Effect on y + + diff --git a/inst/tinytest/_tinysnapshot/ggiplot_multi_complex_kitchen_iid.svg b/inst/tinytest/_tinysnapshot/ggiplot_multi_complex_kitchen_iid.svg new file mode 100644 index 0000000..b1a685e --- /dev/null +++ b/inst/tinytest/_tinysnapshot/ggiplot_multi_complex_kitchen_iid.svg @@ -0,0 +1,349 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +sample: Odds + +Sun & Abraham (2020) + + + + + + + + + + +sample: Odds + +TWFE + + + + + + + + + + +sample: Evens + +Sun & Abraham (2020) + + + + + + + + + + +sample: Evens + +TWFE + + + + + +-5 +0 +5 + + + +-5 +0 +5 +-4 +0 +4 +8 + + + + +-4 +0 +4 +8 + + + + +Time to treatment +Estimate and [80% & 95%] Conf. Int. + +group + + + + + + + + +Sun & Abraham (2020) +TWFE +Staggered treatment: Split mutli-sample + + diff --git a/inst/tinytest/test_ggcoefplot.R b/inst/tinytest/test_ggcoefplot.R index 5a44068..b7a5583 100644 --- a/inst/tinytest/test_ggcoefplot.R +++ b/inst/tinytest/test_ggcoefplot.R @@ -56,3 +56,13 @@ data("base_did", package = "fixest") est_did = feols(y ~ x1 + i(period, treat, 5) | id + period, base_did) p_did = ggcoefplot(est_did) expect_snapshot_plot(p_did, label = "ggcoefplot_did") + + +# +## vcov adjustment (passed through ...) ---- + +p_did_iid_summ = ggcoefplot(summary(est_did, vcov = "iid")) # manual approach +p_did_iid = ggcoefplot(est_did, vcov = "iid") # passed through "..." +expect_snapshot_plot(p_did_iid_summ, label = "ggcoefplot_did_iid") +expect_snapshot_plot(p_did_iid, label = "ggcoefplot_did_iid") # should be identical + diff --git a/inst/tinytest/test_ggiplot.R b/inst/tinytest/test_ggiplot.R index 7d8cbfe..c0cd13f 100644 --- a/inst/tinytest/test_ggiplot.R +++ b/inst/tinytest/test_ggiplot.R @@ -153,3 +153,41 @@ p18 = ggiplot( expect_snapshot_plot(p16, label = "ggiplot_multi_complex") expect_snapshot_plot(p17, label = "ggiplot_multi_complex_mci") expect_snapshot_plot(p18, label = "ggiplot_multi_complex_kitchen") + +# Last one(s): Check vcov adjustment of previous plot +# Manual version, passing via summary first... +p19a = ggiplot( + list( + 'TWFE' = summary(est_twfe_grp, vcov = "iid"), + 'Sun & Abraham (2020)' = summary(est_sa20_grp, vcov = "iid") + ), + main = 'Staggered treatment: Split mutli-sample', + ref.line = -1, + xlab = 'Time to treatment', + multi_style = 'facet', + geom_style = 'ribbon', + ci_level = c(.8, .95), + theme = theme_minimal() + theme( + text = element_text(family = 'HersheySans'), + plot.title = element_text(hjust = 0.5), + legend.position = 'none' + ) +) +# Next, passing as a convenience string (via ...) +p19b = ggiplot( + list('TWFE' = est_twfe_grp, 'Sun & Abraham (2020)' = est_sa20_grp), + vcov = "iid", + main = 'Staggered treatment: Split mutli-sample', + ref.line = -1, + xlab = 'Time to treatment', + multi_style = 'facet', + geom_style = 'ribbon', + ci_level = c(.8, .95), + theme = theme_minimal() + theme( + text = element_text(family = 'HersheySans'), + plot.title = element_text(hjust = 0.5), + legend.position = 'none' + ) +) +expect_snapshot_plot(p19a, label = "ggiplot_multi_complex_kitchen_iid") +expect_snapshot_plot(p19b, label = "ggiplot_multi_complex_kitchen_iid") From cfc35707d4b50295f0803ecdffe84a58931499cc Mon Sep 17 00:00:00 2001 From: Grant McDermott Date: Tue, 12 Dec 2023 08:33:48 -0800 Subject: [PATCH 6/6] NEWS and version bump --- DESCRIPTION | 2 +- NEWS.md | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 8188bcd..c727bc2 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: ggfixest Title: Dedicated ggplot2 methods for fixest objects -Version: 0.0.3.9000 +Version: 0.0.3.9001 Authors@R: c(person(given = "Grant", family = "McDermott", diff --git a/NEWS.md b/NEWS.md index 1adbcbd..23f211e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,12 +1,19 @@ -# ggfixest 0.0.3.9000 (development version) +# ggfixest 0.0.3.9001 (development version) ## New features -- The `aggr_es` function now supports numeric sequences for aggregating -specific period subsets, in addition to the existing keyword strings like "pre" -or "post". This functionality passes through to the higher order functions that -call `aggr_es` under the hood. (#33) - +- The `aggr_es` function now supports numeric sequences for aggregating a +specific subset of periods, in addition to the existing keyword strings like +"pre" or "post". This functionality also passes through to the higher order +plotting functions that call `aggr_es` under the hood. For example, +`ggiplot(est, aggr_eff = 6:8)`. (#33) +- Users can now adjust standard errors for model objects on-the-fly at plot +time, by passing an appropriate argument, e.g. `ggcoefplot(est, vcov = "hc1")`. +These on-the-fly adjustments are done via `summary.fixest`, and so the effect is +just the same as passing an adjusted object directly, e.g. +`ggcoefplot(summary(est, vcov = "hc1"))`. However, it may prove more convenient +for simultaneously adjusting a list of multiple models, e.g. +`ggcoefplot(list(est1, est2, est3), vcov = "hc1")`. (#35) # ggfixest 0.0.3