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())
Another option would be to use facets, which then allows you to vary colors more widely across County
while maintaining the distinction between Habitat
s. Lots of different options for color scales. Some info 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())