0

I have problems with the arrangement of bars in ggplot2 using additionally the package ggpattern.

This is my data:

  # reqired packages
library(tibble)
library(ggplot2)
library(ggpattern)

# example data
data <- tibble::tribble(~time, ~origin, ~destination, ~flow,
                        "2015", "BRA", "CHN", 57,
                        "2016", "BRA", "CHN", -70,
                        "2015", "BRA", "USA", 88,
                        "2016", "BRA", "USA", 200,
                        
                        "2015", "MEX", "CHN", 99,
                        "2016", "MEX", "CHN", 70,
                        "2015", "MEX", "USA", 50,
                        "2016", "MEX", "USA", 100,
                        )

I want that all the destination countries have distinct colors and additionally that there is a distinction between the origin countries.

I have something like this in mind:

# plot
plot <- ggplot(data, aes(x = time,
                         fill = destination)) +
  geom_col_pattern(aes(y = flow,
                       pattern = origin),
                   col = "black", pattern_colour = "grey",
                   pattern_spacing = 0.05, pattern_density = 0.09,
                   pattern_key_scale_factor = 0.5)


plot

which produces following chart:

enter image description here

However, I would prefer to have the bars in such order to have the destinationation countries next to each other. For this plot this would mean that the blue parts are next to eacch other and also the red parts. Or in other words, we first split by destination countries (colors) and then origin countries (ggpattern stripes).

Another thing is that the legend is misleading: there should only be colors in the "destination" legend.

PS: Maybe this approach is a bit problematic when you have positive (eg from "BRA") and negative (eg from "MEX") "flows" in different destination countries in the same year..

Marie Veit
  • 27
  • 5

1 Answers1

2

For your data this could be achieved by mapping on the group aesthetic to order the bars by destination first and by reversing the order of the stack to put the bars for China in 2016 (with both a positive and a negative value) next to each other. Note however, that this will not work in more general cases, e.g. if you have positive and negative values for both or all destination countries. Finally you could use the override.aes argument of guide_legend to get rid of the pattern for the fill legend.

library(ggplot2)
library(ggpattern)

ggplot(data, aes(
  x = time,
  y = flow,
  fill = destination,
  group = paste(destination, origin, sep = ".")
)) +
  geom_col_pattern(
    aes(
      pattern = origin
    ),
    position = position_stack(reverse = TRUE),
    col = "black", pattern_colour = "grey",
    pattern_spacing = 0.05, pattern_density = 0.09,
    pattern_key_scale_factor = 0.5
  ) +
  guides(fill = guide_legend(override.aes = list(pattern = "none")))

enter image description here

stefan
  • 90,330
  • 6
  • 25
  • 51
  • This related answer may also be useful https://stackoverflow.com/questions/62393159/how-can-i-add-hatches-stripes-or-another-pattern-or-texture-to-a-barplot-in-ggp – mfg3z0 May 23 '23 at 01:48