format_p_value(),
get_p_format_style(), and
list_p_format_styles().default, apa,
nejm, lancet, ama,
graphpad, scientific).ggmaplot() gains an optional facet.by
argument to split the MA plot into multiple panels (e.g. one per
contrast or species). Top genes are selected per panel, while point
colors use the same significance thresholds in every panel. Default
output (no facet.by) is unchanged (#498).
stat_cor() and stat_regline_equation()
gain a label.anchor argument. With
label.anchor = "panel" the label is placed at the true
panel-relative position (npc), so labels stay aligned across panels or
facets whose axis ranges differ -
e.g. facet_wrap(scales = "free_y"),
geom_smooth() extending each panel by a different amount,
or separate plots combined with ggarrange(). The default
label.anchor = "data" keeps the previous data-range
placement, so existing plots are unchanged (#248).
geom_bracket() gains an orientation
argument. orientation = "vertical" draws a native vertical
bracket (the bar spans the y axis, the tips point left and the label is
rotated), specified with
ymin/ymax/x.position — useful to
annotate plots where the comparison runs along the y axis, e.g.
Kaplan-Meier curves (it is designed for a continuous x axis). The
default orientation = "horizontal" is unchanged, and it
cannot be combined with coord.flip = TRUE (#456).
ggpaired() gains an opt-in jitter
argument that spreads the paired points horizontally to reduce overlap.
Each subject (id) gets a single offset, so its two points
move together and the connecting line stays intact, and only the
horizontal positions change (the values are never moved). Default
jitter = 0 leaves the plot unchanged (#407).
ggboxplot(), ggviolin() and
ggstripchart() gain an opt-in show.n argument.
When show.n = TRUE, the number of observations
("n = <count>") is displayed at the top of each
group. When the groups are dodged (a
color/fill grouping with a dodging
position), one count is shown per group; otherwise a single
count is shown per x-axis tick. Counts respect
select/remove and are computed per facet.
Default is show.n = FALSE, so existing plots are unchanged
(#598, #627).
ggarrange() gains a spacing argument to
increase the gap between the arranged plots (a long-requested option).
It adds a uniform margin, in text-line units, around each plot. Default
is 0 (no extra space; each plot keeps its own margins, so
existing arrangements are unchanged) (#151).
compare_means() gains an id argument
for paired comparisons. Without it, a paired test
(paired = TRUE) pairs observations by row order, so the
p-value is wrong when the data are not sorted so that the compared
groups align by subject. Passing id (the name of a
subject-identifier column) pairs the observations by id instead —
row-order independent, using only the complete pairs (via
rstatix, so the result matches a direct
rstatix::t_test()/wilcox_test() call). It
works for a two-group, a pairwise (more than two groups) and a
ref.group comparison with
t.test/wilcox.test. Default
(id = NULL) is unchanged (#560).
stat_compare_means() also gains the id
argument, so a paired test can be aligned by subject id directly on a
plot
(e.g. ggpaired(...) + stat_compare_means(paired = TRUE, id = "subject")),
displaying the correct p-value even when the data are not sorted by
subject. Plots without id are unchanged (#560).
geom_pwc() and stat_pwc() gain a
p.adjust.n argument giving the number of comparisons to use
for the p-value adjustment (passed as n to
stats::p.adjust()). Default is NULL (adjust by
the number of computed p-values, unchanged behavior); set it when the
displayed comparisons are a subset of a larger family so the adjustment
reflects that larger size. It must be at least the number of p-values
being adjusted, and applies to the panel-level adjustment
(p.adjust.by = "panel") and the single-comparison case
(#612).
annotate_figure() gains column.titles
and row.titles arguments to add a title above each column
and to the left of each row of an arranged grid (useful for publication
panels). Each accepts a character vector (one title per column / per
row, rendered in bold) or a list of grobs (e.g. built with
text_grob()) for full styling control;
row.titles are rotated 90 degrees. The titles are placed in
reserved space (they do not overlap the plots) and are evenly spaced, so
they assume equal-sized columns / rows (the ggarrange()
default). Default is NULL (no titles; existing figures are
unchanged) (#573).
ggbarplot() gains a numeric.x.axis
argument (already available in ggline() and
ggerrorplot()). With numeric.x.axis = TRUE the
x variable is kept numeric instead of being coerced to a discrete
factor, so bars are drawn at their numeric x positions (e.g. a time
axis). Default is FALSE (unchanged behavior)
(#463).
geom_bracket() and stat_pvalue_manual()
gain a tip.length.ref argument controlling what
tip.length is a fraction of. With the default
tip.length.ref = "data" the tips are a fraction of the data
range (unchanged behavior). With tip.length.ref = "axis"
the tips are a fraction of the y-axis range
(ylim/scale_y_*), which renders at the same
physical fraction across plots and therefore gives visually constant tip
lengths regardless of the data range - useful to keep tips consistent
across facets or across separate plots with different scales (#362).
stat_compare_means(comparisons =) draws its brackets via
ggsignif::geom_signif() and does not support
tip.length.ref; passing it there now emits an informative
message pointing to
stat_pvalue_manual(..., tip.length.ref = "axis") instead of
being silently ignored (#362).
stat_cor() and stat_regline_equation()
gain a label.y.step argument giving the vertical spacing
(in text-line units) between the labels of successive groups. Default is
1.4 (unchanged behavior). Setting
label.y.step = 0 stops the per-group vertical shift so
labels align across facet panels when a factor is mapped to an aesthetic
that also defines the facets (the long-standing “labels climbing stairs
across facets” behavior; #248). This control was inspired by the
vstep argument in the ggpmisc package (by Pedro J. Aphalo),
from which ggpubr’s correlation/regression label-positioning logic was
originally adapted; this is acknowledged via @seealso in
?stat_cor.
ggviolin() gains a drop argument
(passed to ggplot2::geom_violin()), default
TRUE (unchanged behavior). Previously the argument was
silently dropped, so grouped violins where a sub-sample has too few
points to draw a density (which geom_violin() removes,
including from the dodge position) could not be kept aligned with added
boxplots / dot plots. Setting drop = FALSE together with
position = position_dodge(0.8, preserve = "single") now
reserves the empty dodge lane so all geoms stay aligned (#381).
ggarrange() gained the ability to choose which
plot(s) supply the shared legend: common.legend now also
accepts one or several plot indices. common.legend = 2 uses
the second plot’s legend (handy when the first plot’s legend is not
representative, e.g. a group is missing in the first plot), and
common.legend = c(1, 2) keeps and combines the legends of
the listed plots into a single shared block (side by side for
legend = "top"/"bottom", stacked for
"left"/"right") - useful when the arranged
plots genuinely need different legends. The documentation of
common.legend was also clarified:
common.legend = TRUE keeps the first plot’s legend (it
does not merge or validate legends), so plots should share a consistent
scale for a single shared legend to be correct. Logical
TRUE/FALSE behave exactly as before
(#347).
ggdonutchart() gained a label.repel
argument (default FALSE). When TRUE, slice
labels are placed with ggrepel::geom_text_repel() and
connected to their slice with leader lines, so the labels of many small
slices no longer overlap (or get dropped). The default output is
unchanged (#655).
ggboxplot() now accepts a position
argument (e.g. position = position_dodge(0.9)), like
ggviolin()/ggdotplot() already do. Previously
passing position errored
(formal argument "position" matched by multiple actual arguments)
because the dodge was hardcoded; the default is unchanged
(position_dodge(0.8)), so grouped box plots look the same
unless you set it (#615).
ggsummarytable() gains an angle
argument to rotate the summary-table text; default
(angle = 0) is unchanged (#595).
ggmaplot() gains a line.color argument
to set the threshold line color; default (“black”) is unchanged
(#322).
ggarrange() gains a byrow argument
(default TRUE) to fill the plot grid by column
(byrow = FALSE) instead of by row; forwarded to
cowplot::plot_grid() (#225).
stat_regline_equation() gains
coef.digits and rr.digits arguments to control
the number of significant digits shown for the regression-equation
coefficients and R2; defaults (2) reproduce the previous
output (#312).
Added formatting parameters to statistical helpers:
p.format.stylep.digitsp.leading.zerop.min.thresholdp.decimal.markAdded p.format.signif support and related label
handling paths.
stat_pvalue_manual() gains a p.digits
argument (default 3) that formats numeric
p-value label columns for display (e.g. label = "p" or
label = "p.adj"), using the same
format_p_value() engine as stat_anova_test().
This restores clean labels (e.g. 0.0156 instead of
0.015625) with rstatix >= 1.0.0, which now
returns full-precision pairwise p-values. Character labels (significance
symbols, pre-formatted strings, glue expressions) are unaffected. Set
p.digits = NULL to print the raw value.
stat_pvalue_manual() additionally gains
p.format.style, p.leading.zero,
p.min.threshold and p.decimal.mark, matching
the p-value formatting arguments already available in
stat_compare_means(), geom_pwc() and
stat_anova_test(). These are opt-in and default so that the
rendered labels are unchanged; for example
p.min.threshold = 0.001 displays very small p-values as
< 0.001, and p.format.style = "nejm"
applies a journal style.
stat_cor() gains two label-formatting arguments:
r.leading.zero — set to FALSE to drop the
leading zero of the correlation coefficient (e.g. .73
instead of 0.73), completing APA-style reporting together
with p.leading.zero (#540). The dropped leading zero is
preserved through plotmath rendering (the value is quoted so it is not
silently re-normalized back to 0.73 in the default
expression output).p.coef.name — symbol for the p-value label; use
"P" for an uppercase p-value (#541).stat_cor() exposes two new computed variables,
rmse and rmse.label, for the root mean square
deviation (RMSE/RMSD) between x and y — useful
for reporting agreement between paired measurements on the same scale
(e.g. predicted vs. reference values). Display it with
aes(label = after_stat(rmse.label)), or combine it with the
correlation coefficient using paste(). The default label is
unchanged (#458).
stat_cor() can now display the confidence interval
of the correlation coefficient, via the new computed variables
conf.int.low, conf.int.high and
conf.int.label (e.g. "95% CI [0.21, 0.75]")
and a conf.level argument (default 0.95). Show
it with aes(label = after_stat(conf.int.label)), or combine
it with the coefficient using paste(). The confidence
interval is available for method = "pearson" only; it is
NA for Spearman/Kendall. The default label is unchanged
(#418).
ggplot2,
dplyr, and tidyr.size usage to linewidth
where required by recent ggplot2.size -> linewidth
migration for the remaining line layers that still passed the deprecated
size argument: the mean/median reference line added by
gghistogram(add = ...) and
ggdensity(add = ...), and the connector segments of
ggdotchart(add = "segments"). These no longer emit
ggplot2’s “size aesthetic for lines was deprecated” or
“Ignoring empty aesthetic: size” warnings, and the
requested line width is now applied via linewidth.ggmaplot() no longer emits an “Ignoring empty
aesthetic: size” warning on its default call; the point
layer sets size only when the user supplies a value.clean_lock_files() helper.ggrepel dependency to
>= 0.9.2 to keep Ubuntu oldrel (R 4.4.x) CI
dependency resolution working.geom_pwc() now detects an absent ref.group
in a grouped subset via the rstatix_missing_ref_group
condition class raised by recent rstatix (walking the
parent chain with rlang::cnd_inherits()), in addition to
matching the error message. This keeps the “skip ref-less subsets”
behaviour working after rstatix made that error message
clearer (rstatix #153); older rstatix versions are still
handled via the message fallback.rstatix version is now
>= 1.0.0 (the version that introduced the
id argument used by compare_means(id = ), and
the full-precision pairwise p-values relied on by the p-value
formatting).stat_compare_means()
and geom_pwc().geom_pwc() so users
can see which grouped subsets were skipped and why (e.g., missing
ref.group or insufficient levels).ggtheme = NULL to the plotting functions
(e.g. ggscatter(), ggboxplot(),
ggline(), gghistogram(), …) now skips applying
a ggpubr theme, so the plot keeps ggplot2’s default theme or the theme
set globally with theme_set(). Previously an explicit
ggtheme = NULL was treated like an unset argument and
theme_pubr() was still applied. Calls that omit
ggtheme or pass a specific theme are unchanged (#561).compare_means() now adjusts p-values
within each group.by level (and response)
rather than pooling all groups together, so a grouped adjustment matches
filtering to one group and adjusting there. This changes
p.adj values for calls that use group.by;
ungrouped calls are unchanged (#200).stat_compare_means(comparisons = ) now emits a one-time
message (and the docs note) clarifying that the displayed pairwise
p-values are not adjusted for multiple comparisons,
pointing to geom_pwc() / stat_pvalue_manual()
+ compare_means(p.adjust.method = ) for corrected p-values
(#293).rstatix::add_cld(), then place them with
geom_text() (see the “Significance letters” section in
?compare_means). Also covers the per-control letters case
(a = differs from control 1, b = differs from control 2) (#464,
#434).ggbarplot()
(e.g. add = "mean_se") must be faceted with the
facet.by= argument, not by appending
+ facet_wrap()/+ facet_grid(): the summaries
are pre-computed over facet.by, so a manually added facet
pools the bars (and, for stacked bars, the error bars) across all panels
(#739).ggtheme default per function, the p-value
threshold/precision defaults, the stat_compare_means()
label separator (test method name, not correlation coefficient), and the
package Description’s list of p-value formatting styles. Thanks to @erdeyl (#749).stat_compare_means() fatal warning/error
in sparse grouped subsets with modern tidyr).stat_compare_means(label = "p.format")
rounding and formatting control).stat_cor() confidence interval, the stat_cor()
RMSE label, and a manual number of comparisons for p-value adjustment in
geom_pwc()/stat_pwc()..get_brewer_pal() so "YlOrBr" is recognized
correctly.ggexport() to respect
verbose = FALSE by suppressing filename
print() output in multi-file raster/vector exports.format_p_value() by validating non-NULL
p.min.threshold as a single positive finite number.create_p_label() to preserve NA
values in p.format (returning NA_character_
instead of stringifying to "p = NA").theme_pubr() now draws the axis tick marks in black
with linewidth 0.5, matching the axis lines; previously the
ticks inherited a lighter grey/thinner style, visibly inconsistent when
zoomed (#668).theme_pubr() now sets strip.clip = "off"
so the facet strip background border renders at its full
linewidth. With the ggplot2 (>= 3.5.0)
default (strip.clip = "on") the border was clipped to the
strip area, cutting the outer half of the stroke so it looked thinner
and misaligned with the panel when zoomed (follow-up to #668). Note: a
facet label wider than its panel now overflows the strip instead of
being truncated; restore clipping with
+ theme(strip.clip = "on") if needed.xticks.by/yticks.by now anchor the axis
breaks to round multiples of the step (e.g. 0, 100, 200) instead of the
slightly-negative expanded axis minimum, which produced odd labels such
as -20, 80, 180 on bar plots with
ylim = c(0, 400) (#313).%||% operator from rlang; it is
used in geom_bracket() and geom_pwc() but base
R only provides it since R 4.4, so it could be unresolved on the R
(>= 4.1) versions the package supports (#665).stat_welch_anova_test(label = "as_detailed_italic") and
stat_welch_anova_test(label = "as_detailed_expression") now
display the numeric F statistic instead of FALSE. Thanks to
@erdeyl (#749).ggbarplot() now supports mapping alpha to
a discrete grouping variable together with a summary
(e.g. alpha = clarity, add = "mean_ci", position = position_dodge()).
Previously this errored at draw time
("alpha * 255": non-numeric argument to binary operator).
The mean/CI is now computed per subgroup, the bars are faded per the
alpha variable, and the error bars are dodged to stay
aligned with their bars. Bar plots without an alpha
grouping variable are unchanged (#404).ggpar() no longer errors on ggsurvplot
objects (or any plot whose theme uses
ggtext::element_markdown(), e.g. survminer’s risk-table
strata labels). Such markdown label elements are now left intact instead
of triggering an “Only elements of the same class can be merged” error;
output for all other plots is unchanged (#382).geom_pwc() with an explicit list of
comparisons no longer drops a whole facet/panel when a
single requested pair cannot be tested (e.g. a group that is entirely
NA or has fewer than two observations). The untestable
comparison is skipped (with a message) and the remaining valid
comparisons are still drawn (#542).compare_means() and stat_compare_means()
now forward extra test options
(e.g. alternative = "greater") to the paired tests aligned
by subject id, which were previously ignored on that path.
Grouped and faceted paired-id comparisons also skip a
subset that cannot be tested (fewer than two groups or no complete
pairs) instead of failing the whole result/layer, while still reporting
genuinely ambiguous data (e.g. duplicated ids). Thanks to @erdeyl (#732).ggbarplot() now places the error bars of a
stacked bar chart correctly when the data mix positive
and negative values (e.g. above/below-ground measurements). The stacked
error bars are cumulated per sign, matching
position_stack(), so a negative segment’s error bar is
drawn on its own side instead of being displaced to the other side
(previously the misplacement also flipped with the factor-level order).
Stacked charts with single-sign data are unchanged (#426).ggviolin() now keeps grouped violins aligned with their
added box/dot layers by default when a sub-group is too sparse for
geom_violin() to compute a density (a single data point).
Previously the sparse sub-group was dropped from the dodge, so the
remaining violin re-centered and no longer lined up. When
drop/position are left at their defaults and
such a one-point grouped cell is present, the empty dodge lane is now
reserved automatically. Balanced, ungrouped, faceted, and
legitimately-unbalanced plots are unchanged, and an explicit
drop/position still takes precedence
(#381).geom_bracket() (and stat_pvalue_manual())
now draw visible tips for a single bracket placed over a stat-computed
y such as
geom_bar()/geom_histogram(). Previously the
bracket tips collapsed into a flat line because the y-axis range was
trained only on the bracket’s single y.position; the tips
are now sized against the fully-trained panel range at draw time, so
they render correctly even with
coord_cartesian(ylim = ...). Brackets with an already
non-zero y range are unchanged (#631).ggline() now dodges the jittered points together with
the line and error bars. Previously, in a grouped line plot with
add = "jitter" and
position = position_dodge(), only the line and summary
(e.g. mean_se) were dodged while the jittered points stayed
centered, so they no longer sat under their group. The jitter now dodges
by the same width. Plots without a position_dodge() (the
default position = "identity") are unchanged (#436).ggbarplot() now lines the error bars up with the bars
when position = position_dodge2() is used.
position_dodge2() places elements according to their own
width, so the thin error bars did not sit on the centre of the wider
bars they belong to (most visible with preserve = "single"
when one x group has fewer bars than another). The error bars are now
drawn at the actual bar positions. Other positions
(identity, position_dodge(),
position_stack()) are unchanged (#363).geom_bracket() and stat_pvalue_manual()
now place brackets correctly on a transformed y axis
(e.g. scale_y_log10()). y.position is given in
data units but was previously used directly in the scale’s transformed
space, so brackets landed far off (e.g. at 10^30) and
squashed the plot. The bracket y.position is now run
through the scale’s transformation; on an untransformed (identity) scale
this is a no-op, so existing plots are unchanged (#342).ggscatter(),
ggboxplot(), ggviolin(),
ggline(), ggbarplot(),
gghistogram(), ggdensity(),
ggdotplot(), ggstripchart(),
ggerrorplot(), ggecdf(),
ggdotchart(), ggpaired(),
ggqqplot()) now accept the British spelling
colour as an alias for color. Previously
colour was silently ignored (#317).stat_regline_equation() now displays the correct
equation for orthogonal polynomial fits such as
formula = y ~ poly(x, 2). Previously the orthogonal basis
coefficients were printed as if they were raw polynomial coefficients,
giving a wrong equation that did not match the fitted curve. For a
simple poly(x, k) term with an intercept, the equation is
now computed from an equivalent raw = TRUE fit (identical
curve, R², AIC, BIC). Linear, raw = TRUE, and
I(x^2) formulas are unaffected; no-intercept models and
transformed poly arguments (e.g. poly(log(x), 2)) keep
their previous behavior (#653).ggscatterhist() now aligns the marginal plots with the
main scatter plot’s axes. The margins were built from the raw data, so
anything that changed the scatter limits (ellipse = TRUE,
position jitter, explicit
xlim/ylim) left the marginal
histograms/densities misaligned with the scatter. Each margin now
inherits the scatter’s axis range (#220, #420).geom_pwc() now places comparison brackets over the
correct groups when an entire x-axis group has only NA
values. Such a group is dropped before the statistical test runs;
previously the surviving groups were renumbered from 1, which shifted
the remaining brackets left. The bracket positions are now anchored to
the discrete x scale so they stay aligned with the plotted groups
(#575).ggballoonplot() now honors user-supplied
xlab/ylab instead of always blanking the axis
titles; axis titles are still blank by default (#639).ggpar(legend.title = ) now also titles
size and alpha legends, not just
colour/fill/linetype/shape
(#412).facet()/panel.labs: a NAMED
panel.labs vector is now matched to the data levels by
name, fixing mislabeled panels when the order differed; unnamed labels
still map positionally (#643).stat_compare_means() no longer fails with a
“*.npc coord ...” error when a grouped x value
is 0 (or negative); .group_coord() now guards
against a non-positive group index and falls back to the first label
coordinate (#594).ggpar()/plot functions now apply xticks.by
and yticks.by together; an internal else if
previously dropped xticks.by whenever
yticks.by was also supplied (#333).stat_compare_means() now forwards the
family argument to the comparison bracket labels; it was
previously ignored whenever comparisons was set (#592,
#624).ggline() now supports two grouping variables at once
(e.g. color and linetype, or an explicit
group plus color); these are combined into a
single interaction group so the right points are connected. Previously
this errored with “the condition has length > 1” (#616, #375).palette vector no longer emits a spurious “No
shared levels found between names(values) …” warning; the
manual color/fill scale is now only applied to an aesthetic actually
mapped in the plot. Unnamed palettes are unchanged, and a named palette
whose names genuinely don’t match still warns (#642).ggviolin() no longer crashes with
scales = "free" (or
"free_x"/"free_y"). The facet argument
scales was being partial-matched to the violin
scale parameter; it is now read with exact matching, so
scales controls faceting and the violin scale
keeps its default (#398).xlim/ylim are now honored with
orientation = "horizontal" (and
rotate = TRUE). The limits are passed to
coord_flip() instead of a separate
coord_cartesian() that was silently replaced, which also
removes the “Coordinate system already present” warning (#646).ggpar() (and the plot functions) now honor
legend.direction for all legend positions; it was
previously ignored for legend = "top"/"bottom"
(#652).compare_means() no longer errors (“Can’t extract
columns that don’t exist”) when a formula variable name contains a space
(e.g. len ~ `spa ced`); the backticks that R adds to
non-syntactic term names are now stripped before matching data columns
(#385).table_cell_font() and table_cell_bg() can
now style an individual header cell (row = 1), not only
body cells; they previously matched only the core-* grobs
and silently did nothing for the header (#535).ggmaplot() now draws the non-significant (“NS”) points
behind the significant ones, so the up/down-regulated hits are no longer
hidden under the grey NS cloud; the legend order (Up, Down, NS) is
unchanged (#365).ggboxplot() now forwards coef to
geom_boxplot(), so coef = 0 can be used to
omit the whiskers; it was previously dropped by geom_exec()
(#517).tab_add_title() / tab_add_footnote(): the
just argument now actually positions the text —
"center"/"right" anchor the title/footnote
across the table width instead of around a fixed point — and the text is
no longer clipped when it is wider than the table (#302).annotate_figure(): the figure label
(fig.lab) now uses a length-independent horizontal
justification, so labels of different lengths keep the same anchor and
captions align across figures; previously a longer label was shifted
away from the corner (#185).reframe(), slice_head(),
slice_tail(), across(), and
where() functions.linewidth parameter to ggboxplot(),
gghistogram(), ggviolin(), and
ggdensity() for ggplot2 3.4.0+ compatibility. The
size parameter is deprecated for line width in these
functions (#644, #645, #654, #656, @erdeyl).adjust parameter to ggviolin() to
control bandwidth adjustment for kernel density estimation (#552, @erdeyl).bw and adjust parameters to
ggdensity() for bandwidth control (#490, @erdeyl).stat_cor(), stat_compare_means(), and
stat_regline_equation() now use after_stat()
syntax instead of deprecated ..var.. notation in
default_aes (#645, @erdeyl).ggballoonplot() example updated to use
guides(size = "none") instead of deprecated
guides(size = FALSE) (@erdeyl).tidyr::gather() with
tidyr::pivot_longer() in ggballoonplot() and
compare_means() internals (#536, @erdeyl).dplyr::do() with
dplyr::reframe() in compare_means(),
desc_statby(), and internal helpers. Replaced
dplyr::mutate_if() with
dplyr::mutate(across(where())) in
ggsummarytable() (@erdeyl).border() deprecation warning by using
linewidth instead of size in
element_rect() (#644, #654, #656, @erdeyl).size deprecation warnings in
ggscatter() (rug and star plots), ggpaired()
(connecting lines), ggecdf() (ECDF line),
ggdensity() (density lines), geom_bracket(),
and geom_pwc() (#645, @erdeyl).stat_cor() parsing error when
options(OutDec = ",") is set (European decimal separator)
by using decimal.mark = "." in formatC() calls
(#512, @erdeyl).compare_means() error “object ‘group2’ not found”
when using ref.group with method = "anova" or
method = "kruskal.test" (#572, @erdeyl).exact = FALSE workaround from version
0.6.2 that forced non-default behavior on wilcox.test().
Tests now use flexible assertions to ensure compatibility across R
versions (#649, #647)..parse_font() not recognizing decimal font sizes
(e.g., lab.font = c(2.4, "italic", "black")), which caused
label colors to render incorrectly (#659).compare_means() function now sets
exact = FALSE for wilcox.test() and
pairwise.wilcox.test() to maintain backward compatibility
and consistent p-values across R versions (#647).outliers parameter to ggboxplot() to
control the display of outlier points. Set outliers = FALSE
to remove the black dots representing outliers from box plots (#614,
@hswl1314)...p.signif.., ..eq.label..) to modern
after_stat() calls with proper namespace
qualification.ggline() parameter handling for ggplot2 3.4.0+
compatibility:
linewidth parameter for line widthsize parameter for lines with helpful
warning messagesize
parameterafter_stat()
calls that were causing failures in reverse dependency packages
(bSi, PopComm). The
convert_label_dotdot_notation_to_after_stat() function now
properly handles namespace qualification while maintaining backward
compatibility (#638).ggplot2::after_stat() is accessible during plot building,
resolving “could not find function after_stat” errors in downstream
packages.stat_regline_equation() to
display in standard mathematical convention “y = mx + b” instead of “y =
b + mx” (#559, @tshates, @mwaak).gghistogram() tests to handle changes in binning
standardization introduced in ggplot2 4.0.0 (#635, @teunbrand).stat_pvalue_manual() failing when
fill or other aesthetics are provided in the parent ggplot
layer. The function now sets inherit.aes = FALSE by default
to prevent conflicts between parent plot aesthetics and the p-value
annotation data (#621, @fncokg).ggplot2::is.ggplot() with
ggplot2::is_ggplot() in ggpar().data$column syntax to quoted column names in
geom_pwc() for tidyselect 1.2.0+ compatibilityall_of() wrapper in unnest() utility
function for tidyselect compatibilitysize by linewidth in
ggplot2 element_line() and element_rect() functions.stat_regline_equation() by
automatically converting deprecated dot-dot notation
(..eq.label.., ..adj.rr.label..,
..p.signif.., etc.) to after_stat() syntax for
ggplot2 3.4.0+ compatibility (#623, @hinkyisme).add_summary() and
ggerrorplot() for ggplot2 compatibility:
stat_summary() parameters to use
fun, fun.min, and fun.max instead
of deprecated fun.y, fun.ymin, and
fun.ymax (#587, @vlonde).linewidth
instead of size for line-based error plotsggadjust_pvalue() added to adjust p-values
produced by geom_pwc() on a ggplot (#522).gene_expressionggpubr.null_device, whose value should be a function that
creates an appropriate null device. These include:
cowplot::pdf_null_device,
cowplot::png_null_device,
cowplot::cairo_null_device and
cowplot::agg_null_device. Default is
cowplot::pdf_null_device. This is used in functions like
as_ggplot(), which need to open a graphics device to render
ggplot objects into grid graphics objects. This function is used to open
a null device to avoid displaying an unnecessary blank page when calling
ggarrange() or as_ggplot() (#306 and #158).
The default option can be changed using, for example,
options(ggpubr.null_device = cowplot::png_null_device).gadd(): Restoring back random state after setting seed
when adding jittered points. To do so, the seed number is just passed to
position_jitter() and position_jitterdodge(),
which preserve the initial random state ( #177 and #349) .ggpubr now requires a version of
ggrepel >= 0.9.2.9999, which now restores the initial
random state after set.seed(). See
https://github.com/slowkow/ggrepel/issues/228ggpubr now requires a version of
cowplot >= 1.1.1ggtexttable(): doc updated with another example; text
justification for individual cells/rows/columns (#335).ggpie(): setting the default of
clip = "off" in coord_polar() so that
ggpie() does not crop labels (#429)as_ggplot(): using null_device to avoid blank page #306
and #158ggarrange(): using null_device to avoid blank page #306
and #158df is
a tibble.ggexport(): support added for graphics device svg
(#469)ggpie() and ggdonutchart() now fully
reacts to the option lab.font (#502)gather_() in both internal
(.check_data()) and exported functions
(compare_means()) (#513)stat_compare_means(): The dot-dot notation
(..p.signif..) was deprecated in ggplot2 3.4.0;
after_stat(p.signif) should be used; updated so that
..p.signif.. is automatically converted into
after_stat() format without warning for backward
compatibility.desc_statby() doc updated to clarify the difference
between SD (standard deviation) and SE (standard error) (#492)geom_smooth() using formula 'y ~ x' is now
turned off in ggscatter()(#488)ggtext(): fix warning “filter_() was
deprecated in dplyr 0.7.0”.ggqqplot(): the argument conf.int is taken
into account now when specified (#524).ggqqplot(): Fixing the warning: “The following
aesthetics were dropped during statistical transformation: sample”
(#523)rstatix v >=0.7.1.999 for preserving
factor class in emmeans_test() (#386)ggmaplot(): Suppressing ggmaplot warning: Unlabeled
data points (too many overlaps). Consider increasing max.overlaps
(#520)compare_means(): works now when the grouping variable
levels contain the key words group2 or group1 (#450)ggparagraph() : fixing bug about minimum paragraph
length (#408)ggexport(): the verbose argument is now considered when
specified by user (#474)stat_anova_test(),
stat_kruskal_test(), stat_welch_anova_test(),
stat_friedman_test() and geom_pwc() added.
These are flexible functions to add p-values onto ggplot with more
options. The function geom_pwc() is for adding pairwise
comparisons p-values to a ggplot; supported statistical methods include
“wilcox_test”, “t_test”, “sign_test”, “dunn_test”, “emmeans_test”,
“tukey_hsd” and “games_howell_test”.as_npc(), npc_to_data_coordinates() and
get_coord().ggpubr_options() to display allowed global
options in ggpubrggpubr.parse_aes.
Logical indicating whether to parse aesthetic variable names. Default is
TRUE. For example, if you want ggpubr to handle
non-standard column names, like A-A, without parsing, then set this
option to FALSE using
options(ggpubr.parse_aes = FALSE).stat_conf_ellipse: ensure stat returns a data.frame for
compatibility with ggplot2 v>=3.4.0stat_compare_means():
after_stat(p.signif) as the dot-dot
notation (..p.signif..) was deprecated in ggplot2 3.4.0
(#509).ggdensity() and gghistogram(): dot-dot
notation (..density.., ..count..) replaced by
after_stat(density) and after_stat(count),
respectively for compatibility with ggplot2 3.4.0.create_aes():
options(ggpubr.parse_aes = FALSE).digits and table.font.size)
added to ggsummarystats() for changing the summary table
decimal place and text size (#341).stat_pvalue_manual() the argument
hide.ns can be either a logical value (TRUE or FALSE) or a
character value (“p” or “p.adj” for filtering out non significant by
p-value or adjusted p-values).vjust = 0.5 (#301).Capital NS. is no longer displayed by
stat_compare_means() (#171)ggshistogram() to make sure that it
works when:
after_stat(),ggscatter() to make sure that:
ggpubr.parse_aes global option is set to FALSE (#229)ggtexttable() (#125,
#129 and #283):
tab_cell_crossout(): cross out a table cell.tab_ncol(), tab_nrow(): returns, respectively, the
number of columns and rows in a ggtexttable.tab_add_hline(): Creates horizontal lines or separators
at the top or the bottom side of a given specified row.tab_add_vline(): Creates vertical lines or separators
at the right or the left side of a given specified column.tab_add_border(), tbody_add_border(), thead_add_border():
Add borders to table; tbody is for table body and thead is for table
head.tab_add_title() and tab_add_footnote() to
add titles and footnotes (#243).create_aes() added to create aes mapping
from a list. Makes programming easy with ggplot2 (#229).coord.flip added to support adding
p-values onto horizontal ggplots (#179). When adding the p-values to a
horizontal ggplot (generated using coord_flip()), you need
to specify the option coord.flip = TRUE.median_hilow_() and
median_q1q3() - added (@davidlorenz,
#209):
median_hilow_(): computes the sample median and a
selected pair of outer quantiles having equal tail areas. This function
is a reformatted version of Hmisc::smedian.hilow(). The
confidence limits are computed as follows:
lower.limits = (1-ci)/2 percentiles;
upper.limits = (1+ci)/2 percentiles. By default
(ci = 0.95), the 2.5th and the 97.5th percentiles are used
as the lower and the upper confidence limits, respectively. If you want
to use the 25th and the 75th percentiles as the confidence limits, then
specify ci = 0.5 or use the function
median_q1q3().median_q1q3(): computes the sample median and, the 25th
and 75th percentiles. Wrapper around the function median_hilow_() using
ci = 0.5.get_breaks() added to easily create breaks
for numeric axes. Can be used to increase the number of x and y ticks by
specifying the option n. It’s also possible to control axis
breaks by specifying a step between ticks. For example, if by = 5, a
tick mark is shown on every 5 (@Chitanda-Satou,
#258).ggscatterhist() (@juliechevalier,
#176):
ggscatterhist() is now a list of ggplots,
containing the main scatter plot (sp) and the marginal
plots (xplot and yplot), which can be
customized by the end user using the standard ggplot verbsalternative supported in
stat_cor() (#276).position in ggline() to make
position “dodged” (#52).outlier.shape in ggboxplot(). Default is
19. To hide outlier, specify outlier.shape = NA. When jitter is added,
then outliers will be automatically hidden.ggdotchart() using the
option sorting = "none" (#115, #223).weight added in gghistogram()
for creating a weighted histogram (#215)ggscaterhist() takes into account the argument
position in margin.params when marginal plot
is a histogram (#286).ggbarplot() enhanced to better handle the creation of
dodged bar plots combined with jitter points (@aherholt, #176)bracket.shorten added in
stat_pvalue_manual() and geom_bracket(). a
small numeric value in [0-1] for shortening the with of bracket
(#285).bracket.nudge.y added in
stat_pvalue_manual() and geom_bracket().
Vertical adjustment to nudge brackets by. Useful to move up or move down
the bracket. If positive value, brackets will be moved up; if negative
value, brackets are moved down (#281).numeric.x.axis added in
ggerrorplot(); logical value, If TRUE, x axis will be
treated as numeric. Default is FALSE (#280).width is now considered in
ggadd() for plotting error bars (#278).linetype in ggpaired().geom_exec() used in ggpaired() to add
lines between paired points.ggmaplot() now supports two input formats (#198):
ggmaplot():
alpha for controlling point transparency/density (@apcamargo,
#152).label.select to select specific genes to show on the
plot (@apastore, #70)ggadd() the fill argument is considered
for jitter points only when the point shape is in 21:25 (@atakanekiz,
#148).parse added in ggscatter()
and in ggtext(). If TRUE, the labels will be parsed into
expressions and displayed as described in ?plotmath (#250).stroke supported in
ggscatter() and in ggline(). Used only for
shapes 21-24 to control the thickness of points border (@bioguy2018,
#258).stat_cor() function code has been simplified. New
arguments p.accuracy and r.accuracy added; a
real value specifying the number of decimal places of precision for the
p-value and the correlation coefficient, respectively. Default is NULL.
Use (e.g.) 0.01 to show 2 decimal places of precision (@garthtarr, #186, @raedevan6, #114, #270).annotate_figure() manual updated to show how to use of
superscript/subscript in the axis labels (#165).ggtextable() now supports further customization when
theme is specified (#283).font.family is now correctly handled by
ggscatter() (#149)ggpar() arguments are correctly applied using
ggpie() (#277).ggscatter(): When conf.int = FALSE, fill
color is set to “lightgray” for the regression line confidence band (@zhan6073, #111).gghistogram() supports the parameter
yticks.by (@Chitanda-Satou,
#258).ggsummarystats() to create a GGPlot with summary stats
table under the plot ( #251).clean_table_theme() to clean the theme of a table, such
as those created by ggsummarytable()ggbarplot() now supports stacked barplots with error
bars (#245).vjsut in stat_compare_means() to move the
text up or down relative to the bracket.type in geom_bracket() to specify label
type. Can be “text” or “expression” (for parsing plotmath expression);
#253.labeller to the function facet()position in get_legend() to specify legend
positionlegend.grob in ggarrange() to specify a
common legend you want to add onto the combined plot.cor.coef.name in the function
stat_cor(). Can be one of “R” (pearson coef), “rho”
(spearman coef) and “tau” (kendall coef). Uppercase and lowercase are
allowed (@andhamel, #216).digits, r.digits, p.digits in the
function stat_cor(). Integer indicating the number of
decimal places (round) or significant digits (signif) to be used for the
correlation coefficient and the p-value (@raedevan6,
#216).compare_means() adapted to tidyr v>= 1.0.0 by
specifying cols in the unnest() function (@Youguang, #216).stat_pvalue_manual() can now handle an rstatix test
result containing only one group column.stat_central_tendency() to add central
tendency measures (mean, median, mode) to density and histogram
plotsstat_overlay_normal_density() to overlay
normal density plot (with the same mean and SD) to the density
distribution of ‘x’.exact = FALSE is no longer used when
computing correlation in stat_cor() (@tiagochst,
#205)ggpie() keeps now the default order of labels (@WortJohn, #203)geom_bracket() for adding brackets with
label annotation to a ggplot. Helpers for adding p-value or significance
levels to a plot.compare_means() has been adapted to tidyr v1.0.0 (@jennybc, #196)geom_exec() now handles geom_bracket()
argumentsvjust, hide.ns,
step.increase, step.group.by,
color and linetype added in
stat_pvalue_manual()stat_pvalue_manual() can now guess automatically the
significance label column.show.legend added to ggadd()
and add_summary() functions.gghistogram(). Works now when the x
variable is R keyword, such as var, mean, etc. (#192)ggline(), error bars now react automatically to
grouping by line type (#191)step.increase added in
stat_compare_means() to avoid overlap between
brackets.stat_pvalue_manual() x axis variable is no longer
automatically converted into factor. If your x variable is a factor,
make sure that it is converted into factor.stat_pvalue_manual() can automatically handle the
output of rstatix testsggbarplot() and ggviolin() now
automatically create error bars by groups when users forget the option
add.params = list(group = ) (#183).ggarrange() works when either
ncol = 1 or nrow = 1 (@GegznaV, #141.compare_means() set automatically the option
exact = FALSE. This is no longer the case (@stemicha, #141.stat_pvalue_manual() now supports dodged grouped plots
(@emcnerny, #104).position is now handled by
ggdotplot() (@Adam-JJJJJ,
#178)label.sep argument works now in
ggscatter() and stat_cor() (@sbbmu, #150)ggscatter() to avoid freezing when the
add argument is incorrect (@atakanekiz,
#135).The option ref.group was only considered when the
grouping variable contains more than two levels. In that case, each
level is compared against the specified reference group. Now,
ref.group option is also considered in two samples mean
comparisons (@OwenDonohoe,
#118)
Now, ggqqplot() reacts to the argument
conf.int.level (@vsluydts,
#123)
Added error bar color is now inherited from the main plot (@JesseRop, #109)
bxp.errorbar added to
ggboxplot() for adding error bars at the top of the box
plots (@j3ypi, #105.stat_pvalue_manual() for adding p-values
generated elsewhere (@achamess, #81, @grst, #65).alpha option added to ggviolin() @mtmatter, #77bracket.size added to
stat_compare_means() @mtmatter, #43stat_cor() supports R^2 as an option
@philament, #32position added in
gghistogram(). Allowed values include “identity”, “stack”,
“dodge”.ci added in ggerrorplot() @abrar-alshaer,
#94ggscatter() can remove the letter ‘a’ from the
legend, when the argument show.legend.text = FALSE
specified @atsyplenkov,
#106.size option to ggscatter
add.params is supported @retrogenomics,
#94.ggdonutchart() added.Significance levels can be now customized and passed to
stat_compare_means() (@jaison75,
#45).
Editing pdf size is now supported in ggexport() (@JauntyJJS,
#45).
ggscatterhist() the x variable was plotted two
times, on both the plot x & y margins, instead of having, as
expected, a) the x variable on the main plot x margin and 2) the y
variable on the main plot y margin. This has been now fixed.ggdotchart() sorted automatically
within groups when the color argument is specified, even
when groups = NULL. This default behaviour has been now removed. Sorting
within groups is performed only when the argument group is
specified (@sfeds, #90).yticks.by and xticks.by work with NAs
(@j3ypi, #89).New function ggballoonplot() added to visualize a
contingency table.
ggdotchart() can be now used to plot multiple groups
with position = position_dodge() (@ManuelSpinola,
#45).
New function ggscatterhist() to create a scatter
plot with marginal histograms, density plots and box plots.
New theme theme_pubclean(): a clean theme without
axis lines, to direct more attention to the data.
New arguments in ggarrange() to customize plot
labels (@G-Thomson, #41):
New argument method.args added to
stat_compare_means(). A list of additional arguments used
for the test method. For example one might use method.args =
list(alternative = “greater”) for wilcoxon test (@Nicktz, #41).
New argument symnum.args added to
stat_compare_means(). A list of arguments to pass to the
function symnum for symbolic number coding of p-values. For example,
symnum.args <- list(cutpoints = c(0, 0.0001, 0.001, 0.01, 0.05, 1), symbols = c("****", "***", "**", "*", "ns"))
New functions table_cell_font() and
table_cell_bg() to easily access and change the text font
and the background of ggtexttable() cells (@ProbleMaker,
#29).
New argument numeric.x.axis in
ggline(). logical. If TRUE, x axis will be treated as
numeric. Default is FALSE. (@mdphan, #35)
New argument lab.nb.digits in
ggbarplot(). Integer indicating the number of decimal
places (round) to be used (#28). Example:
lab.nb.digits = 2.
New argument tip.length in
stat_compare_means(). Numeric vector with the fraction of
total height that the bar goes down to indicate the precise column.
Default is 0.03. Can be of same length as the number of comparisons to
adjust specifically the tip length of each comparison. For example
tip.length = c(0.01, 0.03).
get_legend() returns NULL when the plot doesn’t
have legend.Now data argument are supported in
stat_compare_means() when the option comparisons are
specified (@emcnerny,
#48)
Now compare_means() returns the same p-values as
stat_compare_means() (@wydty, #15).
stat_compare_means() now reacts to label =
“p.format” when comparisons specified (#28).
Now, the p.values are displayed correctly when ref.group is not the first group (@sehufnkjesktgna, #15).
In ggpar(), now legend.title can be
either a character vector, e.g.: legend.title = “Species” or a list,
legend.title = list(color = "Species", linetype = "Species", shape = "Species").
New argument ellipse.border.remove in
ggscatter() to remove ellipse border lines.
ggscatter(mtcars, x = "mpg", y = "wt",
color = "cyl",
ellipse = TRUE, mean.point = TRUE,
ellipse.border.remove = TRUE)In ggscatter(), the argument mean.point
now reacts to fill color.
Support for text justification added in
ggtexttable() (@cj-wilson,
#15)
The function ggpie() can now display japanese texts.
New argument font.family in ggpie() and in
ggpar() (@tomochan001,
#15).
Using time on x axis works know with ggline() and
ggbarplot() (@jcpsantiago,
#15).
stat_compare_means() now reacts to hide.ns
properly.drawDetails.splitText() exported so that the function
ggparagraph() works properly.ggbarplot(), now labels correspond to the true size
of bars (@tdelhomme,
#15).stat_compare_means() now keeps the default order of
factor levels (@RoKant, #12).gradient_color() and gradient_fill():
change gradient color and fill palettes.clean_theme(): remove axis lines, ticks, texts and
titles.get_legend(): to extract the legend labels from a
ggplot object.as_ggplot(): Transform the output of
gridExtra::arrangeGrob() and
gridExtra::grid.arrange() to an object of class
ggplot.ggtexttable(): to draw a textual table.ggparagraph(): to draw a paragraph of text.annotate_figure() to annotate (arranged) ggplots.text_grob() to create easily a customized text
graphical object.background_image() to add a background image to a
ggplot.theme_transparent() to create a
ggplot with transparent background.gghistogram(), density curve and rug react to the
fill color.ggarrange():
align to specify whether graphs in the
grid should be horizontally (“h”) or vertically (“v”) aligned.legend to remove or specify the legend
position when arranging multiple plots.common.legend to create a common unique
legend for multiple plots.New functions:
ggarrange() to arrange multiple ggplots on the same
page.ggexport() to export one or multiple ggplots to a file
(pdf, eps, png, jpeg).ggpaired() to plot paired data.compare_means() to compare the means of two or multiple
groups. Returns a data frame.stat_compare_means() to add p-values and significance
levels to plots.stat_cor() to add correlation coefficients with
p-values to a scatter plot.stat_stars() to add stars to a scatter plot.Now, the argument y can be a character vector of
multiple variables to plot at once. This might be useful in genomic
fields to plot the gene expression levels of multiple genes at once. see
ggboxplot(), ggdotplot(),
ggstripchart(), ggviolin(),
ggbarplot() and ggline.
The argument x can be a vector of multiple variables
in gghistogram(), ggdensity(),
ggecdf() and ggqqplot().
New functions to edit ggplot graphical parameters:
font() to change the appearance of titles and
labels.rotate_x_text() and rotate_y_text() to
rotate x and y axis texts.rotate() to rotate a ggplot for creating horizontal
plot.set_palette() or change_palette() to
change a ggplot color palette.border() to add/change border lines around a
ggplot.bgcolor() to change ggplot panel background color.rremove() to remove a specific component from a
ggplot.grids() to add grid lines.xscale() and yscale() to change axis
scale.New helper functions:
facet() added to create multi-panel plots (#5).add_summary() to add summary statistics.ggadd() to add summary statistics or a geometry onto a
ggplot.New data set added: gene_citation
New arguments in ggpar(): x.text.angle
and y.text.angle
New arguments in ggpubr functions, see ggboxplot(),
ggdotplot(), ggstripchart(),
ggviolin(), ggbarplot() and
ggline:
combine added to combine multiple y variables on the
same graph.merge to merge multiple y variables in the same
plotting area.select to select which item to display.remove to remove a specific item from a plot.order to order plot items.label, font.label, label.select, repel, label.rectangle
to add and customize labelsfacet.by, panel.labs and short.panel.labs: support for
faceting and customization of plot panelsNew argument grouping.vars in ggtext().
Grouping variables to sort the data by, when the user wants to display
the top n up/down labels.
New arguments in theme_pubr():
palette can be also a numeric vector
of length(groups); in this case a basic color palette is created using
the function grDevices::palette().Now, ggpar() reacts to palette when length(palette)
= 1 and palette is a color name #3.
ggmaplot() now handles situations, where there is
only upregulated, or downregulated genes.
get_palette() to generate a palette of k
colors from ggsci palettes, RColorBrewer palettes and custom color
palettes. Useful to extend RColorBrewer and ggsci to support more
colors.ggpar() function can handle a list of
ggplots.right.show.legend.text in the
ggscatter() function. Use show.legend.text = FALSE to hide
text in the legend.title, submain, subtitle, caption, font.submain, font.subtitle, font.caption
in the ggpar() function.font.family in
ggscatter().ggdensity (gghistogram)
are now shown when data have NA values @chunkaowang,
#1ggtext() for textual annotation.ggscatter(). A logical value.
If TRUE, a star plot is generated.geom_exec(). A helper function used
by ggpubr functions to execute any geom_xx functions in ggplot2. Useful
only when you want to call a geom_xx function without worrying about the
arguments to put in ggplot2::aes().ggbarplot().
theme_classic2() added. Classic theme with
axis lines.ggboxplot(), ggviolin(),
ggdotplot(), ggstripchart(),
gghistogram(), ggdensity(),
ggecdf() and ggqqplot() can now handle one
single numeric vector.# Example
ggboxplot(iris$Sepal.Length)
gghistogram(), when add_density = TRUE, y scale
remains = “..count..”.