Add texture/pattern to only one bar in ggplot

46 Views Asked by At

I am trying to modify the texture of only one bar and I am having issues in the legend.

Here is my data and code

Run3VsRun8_Savings <- data.frame(
  Category = factor(c("4", "5", "6"),
                    levels = c("4", "5", "6")),
  Cooling = c(3,0.5,4),
  NG_Heating = c(-39,-106,-30),
  Total =c(-26,-66,-19),
  Total_1=c(-23,-63,-17))


Run3VsRun8_Savings_long <- gather(Run3VsRun8_Savings, key = "Variable", value = "Value", -Category)

In the above data, I want to add patterns only to the bar showing values for Total_1. The below is the expected outputExpected output

ggplot(data = Run3VsRun8_Savings_long, aes(x = Category, y = Value, fill = Variable, pattern = Variable)) +
  geom_bar_pattern(position = position_dodge2(padding = 0), stat = "identity", color = 'black',
                   pattern_fill = "white",
                   pattern_angle = 55,
                   pattern_density = 0.5,
                   pattern_spacing = 0.025,
                   pattern_key_scale_factor = 0.6) +
  geom_text(aes(label = paste0(Value, "%")), position = position_dodge(width = 1), vjust = -0.6, size = 2.8) +
  geom_vline(xintercept = seq(0.5, length(unique(Run3VsRun8_Savings_long$Category)) - 0.5), 
             linetype = "dashed", color = "black") + 
  scale_fill_manual(
    values = c("Cooling" = "skyblue", "NG_Heating" = "pink", "Total" = "gold", "Total_1" = "gold"),
    labels = c("Cooling" = "Cooling", "NG_Heating" = "Heating", "Total" = "Total_ZERH+HP", "Total_1" = "Total_ZERH+HP+Tight Envelope")
  ) +  
  scale_pattern_manual(values = c('Cooling' = 'none', 'NG_Heating' = 'none', 'Total' = 'none', 'Total_1' = 'stripe'),
                       labels = c('Cooling' = '', 'NG_Heating' = '', 'Total' = '', 'Total_1' = '')) +
  labs(x = "STUDY REGION", y = "COST SAVINGS (%)",
       title = 'Single-Wide Homes') + ylim(-120, 10) +
  theme_minimal() +
  theme(
    legend.position = "bottom",  
    legend.direction = "horizontal",
    legend.box = "horizontal",  
    legend.margin = margin(t = 0, r = 0, b = 0, l = 0),
    legend.title = element_blank(),
    legend.text = element_text(size = 10),
    plot.title = element_text(hjust = 0.5, margin = margin(b = 25), face = 'bold')
  )

The error is probably because I am using both geom_bar_pattern and scale_fill_manual> Not sure how to add texture to only 'Total_1' without messing the legendsMy output with wrong legends

I am facing issues in the legends as shown in this plot.

Thanks for your help

1

There are 1 best solutions below

1
stefan On BEST ANSWER

Legends only get merged when you use the same labels, name, ... Hence, to fix your issue use the same labels in scale_pattern_manual as in scale_fill_manual:

library(ggplot2)
library(ggpattern)

ggplot(
  data = Run3VsRun8_Savings_long,
  aes(x = Category, y = Value, fill = Variable, pattern = Variable)
) +
  geom_bar_pattern(
    position = position_dodge2(padding = 0), 
    stat = "identity", color = "black",
    pattern_fill = "white",
    pattern_angle = 55,
    pattern_density = 0.5,
    pattern_spacing = 0.025,
    pattern_key_scale_factor = 0.6
  ) +
  geom_text(aes(label = paste0(Value, "%")),
    position = position_dodge(width = 1), vjust = -0.6, size = 2.8
  ) +
  geom_vline(
    xintercept = seq(0.5, length(unique(Run3VsRun8_Savings_long$Category)) - 0.5),
    linetype = "dashed", color = "black"
  ) +
  scale_fill_manual(
    values = c(
      "Cooling" = "skyblue", "NG_Heating" = "pink",
      "Total" = "gold", "Total_1" = "gold"
    ),
    labels = c(
      "Cooling" = "Cooling", "NG_Heating" = "Heating",
      "Total" = "Total_ZERH+HP", "Total_1" = "Total_ZERH+HP+Tight Envelope"
    )
  ) +
  scale_pattern_manual(
    values = c(
      "Cooling" = "none", "NG_Heating" = "none",
      "Total" = "none", "Total_1" = "stripe"
    ),
    labels = c(
      "Cooling" = "Cooling", "NG_Heating" = "Heating",
      "Total" = "Total_ZERH+HP", "Total_1" = "Total_ZERH+HP+Tight Envelope"
    )
  ) +
  labs(
    x = "STUDY REGION", y = "COST SAVINGS (%)",
    title = "Single-Wide Homes"
  ) +
  ylim(-120, 10) +
  theme_minimal() +
  theme(
    legend.position = "bottom",
    legend.direction = "horizontal",
    legend.box = "horizontal",
    legend.margin = margin(t = 0, r = 0, b = 0, l = 0),
    legend.title = element_blank(),
    legend.text = element_text(size = 10),
    plot.title = element_text(hjust = 0.5, margin = margin(b = 25), face = "bold")
  ) +
  guides(
    pattern = guide_legend(override.aes = list(
      pattern_spacing = 0.025 
    ))
  )