Home > other >  Bar plot using continuous variable and factor to color bars
Bar plot using continuous variable and factor to color bars

Time:10-08

I have a a dataset that looks like this but much bigger:

County <- rep(c("Alameda", "Clallam", "Clatsop", "Contra Costa", "Coos", "Curry"), each=2)
Habitat <-rep(c("Seagrass","Saltmarsh"), time=6)
Acres <- c("892.03", "6841.43", "5092.35","214.74", "0", "463.06","3165.39","2159.99","263.21", "12.53", "0","83.1")
SVI<-rep(c("0.4701", "0.6146","0.5185", "0.0.4057", "0.529","0.8774"), each=2)

df <- data.frame(County, Habitat, Acres, SVI)

I would like to make a barplot that shows the number of acres for seagrass and saltmarsh by county but I would like the color of the barplot to reflect the SVI value.

So ideally I would have: bars in a range of shades of pink that reflect seagrass SVI value and bars in a range of shades of blue that reflect saltmarsh SVI value. I figured out how to do this for two discrete value but not one categorical and one continuous.

So far I have:

library(ggplot2)
p<-ggplot(data=df, aes(x=County, y=Acres, fill=Habitat, color=SVI))  
  geom_bar(stat="identity", position=position_dodge())

But that's not exactly what I want.

Any suggestions?

Thank you,

Annick

CodePudding user response:

One option is you can use alpha to set the transparency, which will give you the result of a range of colors within a given variable.

ggplot(data=df, aes(x=County, y=Acres, fill=Habitat, alpha=SVI, color = Habitat))  
  geom_bar(stat="identity", position=position_dodge())

enter image description here

Another option would be to use facets, which then allows you to vary colors more widely across County while maintaining the distinction between Habitats. Lots of different options for color scales. Some info here: enter image description here


Data, with a tweak to make Acres and SVI numeric

County <- rep(c("Alameda", "Clallam", "Clatsop", "Contra Costa", "Coos", "Curry"), each=2)
Habitat <-rep(c("Seagrass","Saltmarsh"), time=6)
Acres <- c("892.03", "6841.43", "5092.35","214.74", "0", "463.06","3165.39","2159.99","263.21", "12.53", "0","83.1")
SVI<-rep(c("0.4701", "0.6146","0.5185", "0.04057", "0.529","0.8774"), each=2)

df <- data.frame(County, Habitat, Acres = as.numeric(Acres), SVI = as.numeric(SVI))

CodePudding user response:

You will first need to convert your character variables to numbers:

df$Acres <- as.numeric(df$Acres)
df$SVI   <- as.numeric(df$SVI)

Using two fill scales for dodged bars is tricky. It requires two separate layers, which will not dodge automatically, so require a numeric axis that has to be faked to look discrete. It also requires two gradient fill scales, which can't be done natively in ggplot, but can be done using the ggnewscale extension package:

library(ggnewscale)
library(ggplot2)

ggplot(data = subset(df, Habitat == "Seagrass"),
       aes(x = as.numeric(factor(County)) - 0.2, y = Acres, fill = SVI))  
  geom_col(width = 0.35, color = "gray50")  
  scale_fill_gradient(low = "hotpink", high = "white", name = "Seagrass")  
  ggnewscale::new_scale_fill()  
  geom_col(data = subset(df, Habitat == "Saltmarsh"), width = 0.35,
           aes(x = as.numeric(factor(County))   0.2, fill = SVI),
           color = "gray50")  
  scale_fill_gradient(low = "navy", high = "lightblue", name = "Saltmarsh")  
  scale_x_continuous(breaks = seq_along(levels(factor(df$County))),
                     labels = levels(factor(df$County)), name = "County")  
  theme_minimal(base_size = 16)  
  theme(panel.grid.major.x = element_blank())

enter image description here

  • Related