rggplot2bar-chartggpattern

Add texture/pattern to only one bar in ggplot


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


Solution

  • 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 
        ))
      )