skip to Main Content

I am looking to create a bar plot in R combining data from 2 different dataframes plus using a third variable as fill.

The data:

all_spp <- data.frame(NAME=c("A", "B", "C", "D"), spp=c(9, 5, 8, 6), cat=c("I", "II", "III", "IV") )

listed_spp <- data.frame(NAME=c("A", "B", "C", "D"), en_spp=c(1, 3, 2, 3) )

The data depict protected areas (NAME), the total number of species (spp) versus endangered species (en_spp) and the protection levels of the protected areas (cat). I am trying to create a bar plot depicting total number of species (x=spp) by protected area (y=NAME) coloured in the respective fill for the protection level (fill=cat). On top of each bar per area I would like to show the endangered species (x=en_spp) as a hashed bar.

I have tried combining the two dataframes and using the melt function, however, that does not allow me to use fill=cat, nor does it add a corresponding correct legend.

This is the code I have been trying to use but does not work

ggplot(data=all_spp, aes(x = spp, y = reorder(NAME, spp), fill=cat),) +
  geom_bar(stat = "identity", position="stack") +
  geom_bar(listed_spp, mapping=aes(x=en_spp, y=reorder(NAME, en_spp))) +
  scale_x_continuous(limits = c(0,10), expand = c(0, 0)) +
  theme_bw() +
  theme(axis.text.y=element_text(size=18)) +
  scale_fill_manual(breaks=c("I", "II", "III", "IV"),
                    values = c("I" = "#004B57",
                               "II" ="#007AA2",
                               "III" = "#008DC0",
                               "IV" = "#009DCF"))

Below a photoshopped graph depicting the output I am looking for:
example of stacked barplot with legend

Any ideas for a solution would be appreciated.

2

Answers


  1. You can use the ggpattern package to do this. It’s much like this answer, but with a tweak for the two different datasets.

    library(ggpattern)
    library(ggplot2)  
    
    all_spp <- data.frame(NAME=c("A", "B", "C", "D"), spp=c(9, 5, 8, 6), cat=c("I", "II", "III", "IV") )
    listed_spp <- data.frame(NAME=c("A", "B", "C", "D"), en_spp=c(1, 3, 2, 3) )
    
    ggplot(data = all_spp, aes(x = spp, y = reorder(NAME, spp), fill = cat)) +
      geom_bar(stat="identity") + 
      geom_bar_pattern(data=listed_spp, aes(y=NAME, x=en_spp, pattern = "Endangered"), 
               stat="identity", 
               alpha=0,
               color = "black", 
               pattern_fill = "black",
               pattern_angle = 45,
               pattern_density = 0.1,
               pattern_spacing = 0.025,
               pattern_key_scale_factor = 0.6, inherit.aes=FALSE) + 
      labs(pattern = "", y="Name", x="# Species") + 
      scale_x_continuous(limits = c(0,10), expand = c(0, 0)) +
      theme_bw() +
      theme(axis.text.y=element_text(size=18)) +
      scale_fill_manual(breaks=c("I", "II", "III", "IV"),
                        values = c("I" = "#004B57",
                                   "II" ="#007AA2",
                                   "III" = "#008DC0",
                                   "IV" = "#009DCF"))
    

    Created on 2024-02-02 with reprex v2.0.2

    Login or Signup to reply.
  2. To reproduce your example plot, this will work. You example usesscale_pattern_manual() to replicate your example pattern. See this link for more information.

    library(ggplot2)
    library(ggpattern)
    
    all_spp <- data.frame(NAME=c("A", "B", "C", "D"),
                          spp=c(9, 5, 8, 6), 
                          cat=c("I", "II", "III", "IV"))
    
    listed_spp <- data.frame(NAME=c("A", "B", "C", "D"), 
                             en_spp=c(1, 3, 2, 3))
    
    ggplot() +
      geom_bar(data = all_spp,
               aes(x = spp, y = reorder(NAME, spp), fill = cat),
               stat = "identity",
               position="stack") +
      geom_bar_pattern(data = listed_spp,
               aes(x = en_spp, y=reorder(NAME, en_spp), pattern = "Endangered Species"),
               stat = "identity", 
               position ="stack",
               fill = NA,
               colour = "black",
               pattern_density = 0.5,
               pattern_spacing = .03,
               pattern_fill = NA,
               pattern_colour = "black",
               pattern_key_scale_factor = 0.6,
               inherit.aes = FALSE) +
      scale_pattern_manual(values = "stripe", name = "") +
      labs(x = "Number of Species", y = "Name") +
      theme_bw() +
      theme(axis.text.y=element_text(size=18),) +
      scale_fill_manual(breaks=c("I", "II", "III", "IV"),
                        values = c("I" = "#004B57",
                                   "II" ="#007AA2",
                                   "III" = "#008DC0",
                                   "IV" = "#009DCF"),
                        name = "Category")
    

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search