Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to complete barplot bars to 100% with a distinct style?

Plotting a bar plot where Y axis reflects percents, how can I "complete" each bar to 100%?

Example

Consider the following plot:

library(ggplot2)
library(tibble)

my_df <- tribble(~step, ~prop,
                   "a", 1,
                   "b", 0.8,
                   "c", 0.55,
                   "d", 0.2
)

my_df |> 
  ggplot(aes(x = step,
             y = prop)) +
  geom_col()

Created on 2023-09-10 with reprex v2.0.2

How can I create a plot that completes each bar to 100% out of it with dashed lines? Something like: enter image description here

like image 974
Emman Avatar asked Dec 11 '25 16:12

Emman


1 Answers

One option would be use a second geom_col to first draw 100% bars, then place your bars on top of it where we have to explicitly set the outline color. Note: One downside, which I did not realize at first, is that the outline of the background bars shouldn't but is visible. A fix would be to set the linewidth and or the bar width as suggested by @jkd and @r2evans in their comments. A second and cleaner option would be to use a geom_path (see below).

library(ggplot2)
library(tibble)

my_df <- tribble(
  ~step, ~prop,
  "a", 1,
  "b", 0.8,
  "c", 0.55,
  "d", 0.2
)

my_df |>
  ggplot(aes(
    x = step,
    y = prop
  )) +
  geom_col(aes(y = 1), color = "red", linetype = "dashed", fill = NA) +
  geom_col(color = "grey35")

IMHO, the cleanest option to achieve the same result would be to use a geom_path which however requires some effort to create an appropriate dataset to draw the paths:

library(ggplot2)
library(tibble)
library(dplyr, warn = FALSE)

make_path <- function(y, width = .9) {
  if (y < 1) {
    data.frame(
      x = width / 2 * c(-1, -1, 1, 1),
      y = c(y, 1, 1, y)
    )
  } else {
    data.frame(x = numeric(0), y = numeric(0))
  }
}

df_path <- my_df |>
  mutate(step = factor(step)) |> 
  reframe(make_path(prop), .by = step) |>
  mutate(x = as.numeric(step) + x)

my_df |>
  ggplot(aes(
    x = step,
    y = prop
  )) +
  geom_col(color = "grey35") +
  geom_path(
    data = df_path,
    aes(x = x, y = y, group = step),
    color = "red", linetype = "dashed"
  )

like image 75
stefan Avatar answered Dec 14 '25 06:12

stefan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!