This is a modification of ggplot2::position_stack()
for creating diverging
bar charts. In order to use this function, you must set a fill aesthetic
(and that aesthetic should probably be a factor). This function will
automatically break your chart into negative and positive values and display
them in the same order as your fill levels.
Arguments
- vjust
Vertical adjustment for geoms that have a position (like text or points), not a dimension (like bars or areas). Set to 0 to align with the bottom, 0.5 for the middle, and 1 (the default) for the top.
- break_after
Either an integer index or character value that represents the last positive level. The default,
NULL
, will split the levels halfway (with fewer positive levels if the total number of levels is odd).- fill
If
TRUE
will automatically scale bars to 100% as withposition_fill()
- reverse
If
TRUE
, will reverse the default stacking order.
Examples
library(ggplot2)
# Example data
test_df <- tibble::tribble(
~q, ~response, ~prop,
'a', 'Yes', 0.25,
'a', 'Mostly', 0.25,
'a', 'Somewhat', 0.25,
'a', 'Not Yet', 0.25,
'b', 'Yes', 0.4,
'b', 'Mostly', 0.3,
'b', 'Somewhat', 0.2,
'b', 'Not Yet', 0.1
) |>
dplyr::mutate(
response = forcats::fct_inorder(response),
q = forcats::fct_inorder(q)
)
# Default diverging with text
# In interactive use, this can also be run with `position = "diverge"`
test_df |>
ggplot(aes(prop, q, fill = response)) +
geom_col(position = position_diverge()) +
geom_text(aes(label = scales::percent(prop,)),
position = position_diverge(vjust = 0.5)) +
geom_vline(xintercept = 0) +
tntp_style(family = "sans") +
# Reverse legend to match horizontal bar order
guides(fill = guide_legend(reverse = TRUE)) +
# Adjust axis labels to be positive on both sides
scale_x_continuous(labels = ~scales::percent(abs(.)))
# Custom breaks with the break_after parameter
test_df |>
ggplot(aes(q, prop, fill = response)) +
geom_col(position = position_diverge(break_after = 'Yes')) +
geom_hline(yintercept = 0) +
tntp_style(family = "sans") +
# Adjust axis labels to be positive on both sides
scale_y_continuous(labels = ~scales::percent(abs(.)))