How to map variable values to pattern fills - ggplot / ggpattern (

Viewed 322
ggplot(unique(films2[,c("film","word.len.avg")]) ,aes(film,word.len.avg,fill=film,))+
  geom_bar_pattern(stat="identity", 
                   pattern = 
                     
                     c(
                       "circle", 
                       "stripe",  
                       "none",  
                       "wave", 
                       "crosshatch" 
                     ),
                   pattern_angle = c(rep(45, ), 
                                     rep(60, ), 
                                     rep(45, ),
                                     rep(45, ),
                                     rep(45,)),
                   fill            = 'white',
                   colour          = 'black', 
                   pattern_density = .35, 
                   pattern_fill    = 'darkblue',
                   pattern_colour  = 'darkblue'
                   
  ) +
  scale_x_discrete(breaks = c("dial.m.for.murder", "pscyho", "rear.window", "rope", "vertigo"), 
                   labels = c("Dial M for Murder", "Psycho", "Rear Window", "Rope", "Vertigo"))+
  theme_bw() +
  aes(pattern = film)+
theme(legend.position = "right") + 
  coord_fixed(ratio = 1.5)+
  scale_pattern_spacing_discrete(range = c(0.01, 0.05)) 

Hi I have the above code for a bar graph with pattern fills. See associated image below. This is code I cobbled together from various sources on stack overflow, and I'm pleased it finally works in that I now finally have five bars with a different fill pattern in each. However, it's clear that these patterns are not necessarily associated with a specific film (there are five values for film). I'm wondering how I can get the pattern fills to be mapped to specific films, because at the moment the legend won't show, and I'm assuming it's because of this (i.e. things haven't been mapped properly?). Any advice would be greatly appreciated. Maroenter image description here

Just to add, I found this online https://evamaerey.github.io/flipbooks/ggpattern/ggpattern#28 which sort of does what I want it to do, but doesn't look as nice as the one above. This will do for now, but if anyone has any suggestions for how to combine the two, or how to adapt the code above so that I can get the key to show, that would be appreciated too! Thank you!!!

1 Answers

When you set things outside of aes it is like setting them outside of the legend.

If there is something, like angle or pattern that you're willing to lose control of you can get this into a legend. For example:

ggplot(unique(films2[,c("film","word.len.avg")], aes(film, word.len.avg,)) + 
  geom_col_pattern(aes(pattern = film, fill = film, 
                       pattern_angle = film, pattern_spacing = film),
                   fill            = 'white',
                   colour          = 'black',
                   pattern_density = .35,
                   pattern_fill    = 'darkblue',
                   pattern_colour  = 'darkblue') +
  theme_bw() +
  theme(legend.position = "right") + 
  coord_fixed(ratio = 1.5)+
  scale_pattern_spacing_discrete(range = c(0.01, 0.05))

enter image description here

You may have noticed that I used geom_col_pattern().

I saw that you have aes(pattern = film) this line is not doing anything, it needs to be tied to a geom_ or stat_ call.

If you are set on how your variables are presented, you can use scale_color_manual and scale_fill_manual calls to do this.

For example:

ggplot(unique(films2[,c("film","word.len.avg")], aes(film, word.len.avg,, fill = film))+
  geom_bar_pattern(stat="identity", 
                   pattern = c("circle", "stripe", "none",
                               "wave", "crosshatch" ),
                   pattern_angle = c(45, 60, rep(45, 3)),
                   # fill            = 'white',
                   colour          = 'black', 
                   pattern_density = .35, 
                   pattern_fill    = 'darkblue',
                   pattern_colour  = 'darkblue'
                   
  ) + scale_fill_manual(values = setNames(c("darkred", "darkblue", "white", 
                                                    "lightyellow", "gray"),
                                                  unlist(df$film))) +
  scale_x_discrete(breaks = c("dial.m.for.murder", "pscyho", 
                              "rear.window", "rope", "vertigo"), 
                   labels = c("Dial M for Murder", "Psycho", "
                              Rear Window", "Rope", "Vertigo"))+
  theme_bw() +
  # aes(pattern = film)+
  theme(legend.position = "right") + scale_pattern_fill_viridis_c() +
  coord_fixed(ratio = 1.5)+
  scale_pattern_spacing_discrete(range = c(0.01, 0.05))

enter image description here

Related