x-axis starting value for diverging plot

Viewed 66

How can I change the "x-axis starting value" from the diverging bar chart below (extracted from here), so that the vertical axis is set at 25 instead of 0. And therefore the bars are drawn from 25 and not 0.

For instance, I want this chart:

enter image description here

To look like this:

enter image description here


EDIT It it not the label I want to change, it is how the data is plotted. My apologies if I wasn't clear. See example below:

Another example to make it clear:

enter image description here

3 Answers

You can provide computed labels to an (x-)scale via scale_x_continuous(labels = function (x) x + 25).

If you also want to change the data, you’ll first need to offset the x-values by the equivalent amount (in the opposite direction):

Example:

df = tibble(Color = c('red', 'green', 'blue'), Divergence = c(5, 10, -5))
offset = 2

df %>%
    mutate(Divergence = Divergence - offset) %>% 
    ggplot() +
    aes(x = Divergence, y = Color) +
    geom_col() +
    scale_x_continuous(labels = function (x) x + offset)

enter image description here

I'm still not 100% clear on your intended outcome but you can "shift" your data by adding/subtracting 25 from each value, e.g.

Original plot:

library(tidyverse)
library(gapminder)

set.seed(123)

gapminder_subset <- gapminder %>% 
  pivot_longer(-c(country, continent, year)) %>% 
  filter(year == "1997" | year == "2007") %>% 
  select(-continent) %>% 
  filter(name == "gdpPercap") %>% 
  pivot_wider(names_from = year) %>% 
  select(-name) %>% 
  mutate(gdp_change = ((`2007` - `1997`) / `1997`) * 100) %>% 
  sample_n(15)


ggplot(data = gapminder_subset,
       aes(x = country, y = gdp_change)) +
  geom_bar(stat = "identity") +
  coord_flip()

example_3.png

subtract 25:

library(tidyverse)
library(gapminder)

set.seed(123)

gapminder_subset <- gapminder %>% 
  pivot_longer(-c(country, continent, year)) %>% 
  filter(year == "1997" | year == "2007") %>% 
  select(-continent) %>% 
  filter(name == "gdpPercap") %>% 
  pivot_wider(names_from = year) %>% 
  select(-name) %>% 
  mutate(gdp_change = ((`2007` - `1997`) / `1997`) * 100) %>% 
  sample_n(15)


ggplot(data = gapminder_subset,
       aes(x = country, y = gdp_change)) +
  geom_bar(stat = "identity") +
  coord_flip()

example_4.png

If you combine that with my original relabelling I think that's the solution:

ggplot(data = gapminder_subset,
       aes(x = country, y = gdp_change - 25)) +
  geom_bar(stat = "identity") +
  coord_flip() +
  scale_y_continuous(breaks = c(-25, 0, 25, 50),
                     labels = c(0, 25, 50, 75))

example_5.png

The answers that existed at the time that I'm writing this are suggesting to change the data or to change the label. Here, I'm proposing to change neither the data nor the labels, and instead just change where the starting position of a bar is.

First, for reproducibility, I took @jared_mamrot's approach for the data subset.

library(gapminder)
library(tidyverse)

set.seed(123)

gapminder_subset <- gapminder %>% 
  pivot_longer(-c(country, continent, year)) %>% 
  filter(year == "1997" | year == "2007") %>% 
  select(-continent) %>% 
  filter(name == "gdpPercap") %>% 
  pivot_wider(names_from = year) %>% 
  select(-name) %>% 
  mutate(gdp_change = ((`2007` - `1997`) / `1997`) * 100) %>% 
  sample_n(15)

Then, you can set xmin = after_scale(25). You'll get a warning that xmin doesn't exists, but it does exist after the bars are reparameterised to rectangles in the ggplot2 internals (which is after the x-scale has seen the data to determine limits). This effectively changes the position where bars start.

ggplot(gapminder_subset,
       aes(gdp_change, country)) +
  geom_col(aes(xmin = after_scale(25)))
#> Warning: Ignoring unknown aesthetics: xmin

Created on 2021-06-28 by the reprex package (v1.0.0)

Related