Is there a way to plot the change per period with a line plot in a bar plot with ggplot2?

Viewed 37

I have the following code which prints a bar plot that shows the cumulated installed capacity for wind energy and pv in Germany from 2000 until 2019. I was wondering if there is a way to add a line to the plot that shows the difference per period for each technology?

library(ggplot2)

wind <- c(6095, 8754, 12001, 14609, 16629,
          18428, 20621, 22247, 23903, 25777,
          27190, 29060, 30989, 33729, 38115,
          41651, 45910, 50777, 52931, 53912)

pv <- c(110, 180, 324, 435, 1105, 2056, 2899,
        4170, 5120, 10566, 18006, 25916, 34077,
        36710, 37900, 39224, 40716, 42492, 45452, 49395)

year <- c(2000, 2001, 2002, 2003, 2004, 2005,
          2006, 2007, 2008, 2009, 2010, 2011,
          2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019)

df <- data.frame(year, wind, pv) %>%
  pivot_longer(cols = 2:3)

p1 <- ggplot(df, aes(fill=name, y=value, x=year)) + 
  geom_bar(position="stack", stat = "identity") +
  ylab("MW") + theme(axis.text.x = element_text(angle = 45, vjust = .6)) +
  scale_fill_discrete(name = "Technology", labels = c("wind", "pv"))

p1
1 Answers

First compute the lagged differences by column or by technology. Any of the two methods below will do it, the second is perhaps more readable.

df <- data.frame(year, wind, pv) %>%
  mutate(across(wind:pv, function(.x) {.x - lag(.x)})) %>%
  pivot_longer(-1)

df <- data.frame(year, wind, pv) %>%
  pivot_longer(-1) %>%
  group_by(name) %>%
  mutate(value = value - lag(value))

Now plot exactly like in the question.

p1 <- ggplot(df, aes(fill=name, y=value, x=year)) + 
  geom_bar(position="stack", stat = "identity") +
  scale_fill_discrete(name = "Technology", labels = c("wind", "pv")) +
  ylab("MW") + 
  theme(axis.text.x = element_text(angle = 45, vjust = .6))

p1

enter image description here


As for a graph with the original data bars and the differences plotted as superimposed lines, here is a solution. The data.frame df is created first, transformed and piped into ggplot. The lines are drawn in different shades of red and blue.
Also, I have reversed the legend labels' order.

df <- data.frame(year, wind, pv)

df %>%
  pivot_longer(-1) %>%
  group_by(name) %>%
  mutate(value_diff = value - lag(value)) %>%
  ggplot(aes(x = year, fill = name)) +
  geom_bar(aes(y = value), position="stack", stat = "identity") +
  geom_line(aes(y = value_diff, color = name)) +
  scale_color_manual(name = "Technology", 
                     breaks = c("pv", "wind"), 
                     values = c("red", "blue")) +
  scale_fill_discrete(name = "Technology", labels = c("pv", "wind")) +
  ylab("MW") +
  theme(axis.text.x = element_text(angle = 45, vjust = .6))

enter image description here

Related