Search code examples
rggplot2graphtidyverse

Pyramid density plot in R


i'm trying to make a Pyramid density plot, but I can't place the X axis (Years) between the densities.

I wanted the densities (blue and red) to be more spaced out and between them there was the year

#data base

historical_spending <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2024/2024-02-13/historical_spending.csv')

#graph

df <- historical_spending |> 
  select(Year,Flowers, Candy)

ggplot(df, aes(x = Year)) + 
  geom_density(data = df, aes(x = Flowers, y = ..density..), fill = "blue", alpha = 0.5) +
  geom_density(data = df, aes(x = Candy, y = -..density..), fill = "red", alpha = 0.5) +
  scale_y_continuous(labels = abs, limits = max(df$Flowers) * c(-0.02,0.02)) +
  coord_flip()



Solution

  • I don't think geom_density is the right tool here. Density measures the probability of finding an observation within a particular range. It seems that you are looking for a smooth line connecting annual measurements. For something bespoke like this, you should calculate polygons using splines and draw the components as annotations:

    library(tidyverse)
    library(geomtextpath)
    
    historical_spending |> 
      select(Year,Flowers, Candy) |>
      reframe(time = seq(min(Year), max(Year), len = 250),
              Candy = -splinefun(Year, Candy)(time) - 3,
              Flowers = splinefun(Year, Flowers)(time) + 3) %>%
      reframe(time = c(min(time), time, max(time)),
              Candy = c(-3, Candy, -3),
              Flowers = c(3, Flowers, 3)) %>%
      pivot_longer(-time) %>%
      ggplot(aes(value, time, fill = name)) +
      annotate("textsegment", x = -3, xend = 3, yend = historical_spending$Year,
               label = historical_spending$Year, y = historical_spending$Year,
               size = 5, color = "gray30", linewidth = 0.1) +
      geom_polygon(alpha = 0.7) +
      annotate("segment", x = c(-23, 3), xend = c(-3, 23), 
               y = 2009.5, yend = 2009.5) +
      annotate("text", x = c(-10, 10), y = 2022.5, label = c("Candy", "Flowers"),
               size = 8) +
      annotate("segment", x = c(seq(-23, -3, 2.5), seq(3, 23, 2.5)),
               xend = c(seq(-23, -3, 2.5), seq(3, 23, 2.5)), y = 2009.5,
               yend = 2009.4, linewidth = 0.2) +
      annotate("text", x = c(seq(-23, -3, 5), seq(3, 23, 5)), y = 2009.1,
               label = c(seq(20, 0, -5), seq(0, 20, 5)), size = 5) +
      scale_fill_manual(NULL, values = c("orangered", "deepskyblue4"), 
                        guide = "none") +
      theme_void(base_size = 20)  +
      xlab("Average annual spend ($)") +
      theme(axis.title.x = element_text(size = 20, margin = margin(0, 10, 10, 10)))
    

    enter image description here