1

I have this stacked-bar chart with a facet grid. Instead of the four colours used, I want to use the texture of different kinds. I am changing from coloured to texture to make each bar different if printed on black and white paper.

library(ggplot2)
library(reshape2)
set.seed(199)
MB_RMSE_sd1 <-  runif(12, min = 0, max = 2)
TMB_RMSE_sd1 <- runif(12, min = 0, max = 2)
MB_RMSE_sd3 <-  runif(12, min = 2, max = 5)
TMB_RMSE_sd3 <- runif(12, min = 2, max = 5)
MB_RMSE_sd5 <- runif(12, min = 5, max = 10)
TMB_RMSE_sd5 <- runif(12, min = 5, max = 10)
MB_RMSE_sd10 <-  runif(12, min = 7, max = 16)
TMB_RMSE_sd10 <- runif(12, min = 7, max = 16)
MB_MAE_sd1 <-  runif(12, min = 0, max = 2)
TMB_MAE_sd1 <- runif(12, min = 0, max = 2)
MB_MAE_sd3 <-  runif(12, min = 2, max = 5)
TMB_MAE_sd3 <- runif(12, min = 2, max = 5)
MB_MAE_sd5 <-  runif(12, min = 5, max = 10)
TMB_MAE_sd5 <- runif(12, min = 5, max = 10)
MB_MAE_sd10 <-  runif(12, min = 7, max = 16)
TMB_MAE_sd10 <- runif(12, min = 7, max = 16)

ID <- rep(rep(c("N10_AR0.8", "N10_AR0.9", "N10_AR0.95", "N15_AR0.8", "N15_AR0.9", "N15_AR0.95", "N20_AR0.8", "N20_AR0.9", "N20_AR0.95", "N25_AR0.8", "N25_AR0.9", "N25_AR0.95"), 2), 1)
df1 <- data.frame(ID, MB_RMSE_sd1, TMB_MAE_sd1, MB_RMSE_sd3, TMB_MAE_sd3, MB_RMSE_sd5, TMB_MAE_sd5, MB_RMSE_sd10, TMB_MAE_sd10)
reshapp1 <- reshape2::melt(df1, id = "ID")

NEWDAT <- data.frame(value = reshapp1$value, year = reshapp1$ID, n = rep(rep(c("10", "15", "20", "25"), each = 3), 16), Colour = rep(rep(c("RMSE_MB", "RMSE_TMB", "MAE_MB", "MAE_TMB"), each = 12), 4), sd = rep(rep(c(1, 3, 5, 10), each = 48), 1),  phi = rep(rep(c("0.8", "0.9", "0.95"), 16), 4))

NEWDAT$sd <- with(NEWDAT, factor(sd, levels = sd, labels = paste("sd =", sd)))
NEWDAT$year <- factor(NEWDAT$year, levels = NEWDAT$year[1:12])
NEWDAT$n <- with(NEWDAT, factor(n, levels = n, labels = paste("n = ", n)))

ggplot() +
  geom_bar(data=NEWDAT[NEWDAT$Colour %in% c("RMSE_MB", "RMSE_TMB"),], 
           aes(x = phi, y=value, fill=rev(Colour)), stat="identity") +
  geom_bar(data=NEWDAT[NEWDAT$Colour %in% c("MAE_MB", "MAE_TMB"),], 
           aes(x=phi, y=-value, fill=Colour), stat="identity") +
  geom_hline(yintercept=0, colour="grey40") +
  facet_grid(sd ~ n, scales = "free") +
  scale_fill_manual(breaks=c("MAE_MB", "MAE_TMB", "RMSE_MB", "RMSE_TMB"),
                    values=c("red","blue","orange","green")) +
  scale_y_continuous(expand = c(0, 0), label = ~abs(.)) + 
  guides(fill=guide_legend(reverse=TRUE)) +
  labs(fill="") + theme_bw() +
  theme(axis.text.x=element_text(angle=-90, vjust=0.5)) 

Here is its output

I have visited Filling bars in barplot with textiles in ggplot2 [duplicate] and How to add texture to fill colours in ggplot2 but because of the complexity of my case I am unable to apply the answers therein.

Daniel James
  • 1,381
  • 1
  • 10
  • 28

1 Answers1

2

You may want to try the package {ggpattern} which would be a nice way to print a plot on Black and White Paper.


library(ggplot2)
library(reshape2)
library(ggpattern)

set.seed(199)

MB_RMSE_sd1 <- runif(12, min = 0, max = 2)
TMB_RMSE_sd1 <- runif(12, min = 0, max = 2)
MB_RMSE_sd3 <- runif(12, min = 2, max = 5)
TMB_RMSE_sd3 <- runif(12, min = 2, max = 5)
MB_RMSE_sd5 <- runif(12, min = 5, max = 10)
TMB_RMSE_sd5 <- runif(12, min = 5, max = 10)
MB_RMSE_sd10 <- runif(12, min = 7, max = 16)
TMB_RMSE_sd10 <- runif(12, min = 7, max = 16)
MB_MAE_sd1 <- runif(12, min = 0, max = 2)
TMB_MAE_sd1 <- runif(12, min = 0, max = 2)
MB_MAE_sd3 <- runif(12, min = 2, max = 5)
TMB_MAE_sd3 <- runif(12, min = 2, max = 5)
MB_MAE_sd5 <- runif(12, min = 5, max = 10)
TMB_MAE_sd5 <- runif(12, min = 5, max = 10)
MB_MAE_sd10 <- runif(12, min = 7, max = 16)
TMB_MAE_sd10 <- runif(12, min = 7, max = 16)

ID <- rep(rep(c("N10_AR0.8", "N10_AR0.9", "N10_AR0.95", "N15_AR0.8", "N15_AR0.9", "N15_AR0.95", "N20_AR0.8", "N20_AR0.9", "N20_AR0.95", "N25_AR0.8", "N25_AR0.9", "N25_AR0.95"), 2), 1)
df1 <- data.frame(ID, MB_RMSE_sd1, TMB_MAE_sd1, MB_RMSE_sd3, TMB_MAE_sd3, MB_RMSE_sd5, TMB_MAE_sd5, MB_RMSE_sd10, TMB_MAE_sd10)
reshapp1 <- reshape2::melt(df1, id = "ID")

NEWDAT <- data.frame(value = reshapp1$value, year = reshapp1$ID, n = rep(rep(c("10", "15", "20", "25"), each = 3), 16), Colour = rep(rep(c("RMSE_MB", "RMSE_TMB", "MAE_MB", "MAE_TMB"), each = 12), 4), sd = rep(rep(c(1, 3, 5, 10), each = 48), 1), phi = rep(rep(c("0.8", "0.9", "0.95"), 16), 4))

NEWDAT$sd <- with(NEWDAT, factor(sd, levels = sd, labels = paste("sd =", sd)))
NEWDAT$year <- factor(NEWDAT$year, levels = NEWDAT$year[1:12])
NEWDAT$n <- with(NEWDAT, factor(n, levels = n, labels = paste("n = ", n)))


ggplot() +
    geom_col_pattern(
        data = NEWDAT[NEWDAT$Colour %in% c("RMSE_MB", "RMSE_TMB"), ],
        aes(x = phi, y = value, pattern = rev(Colour), pattern_angle = rev(Colour)),
        fill            = "white",
        colour          = "black",
        pattern_density = 0.1,
        pattern_fill    = "black",
        pattern_colour  = "black"
    ) +
    geom_col_pattern(
        data = NEWDAT[NEWDAT$Colour %in% c("MAE_MB", "MAE_TMB"), ],
        aes(x = phi, y = -value, pattern = Colour, pattern_angle = Colour),
        fill            = "white",
        colour          = "black",
        pattern_density = 0.1,
        pattern_fill    = "black",
        pattern_colour  = "black"
    ) +
    geom_hline(yintercept = 0, colour = "grey40") +
    facet_grid(sd ~ n, scales = "free") +
    scale_fill_manual(
        breaks = c("MAE_MB", "MAE_TMB", "RMSE_MB", "RMSE_TMB"),
        values = c("red", "blue", "orange", "green")
    ) +
    scale_y_continuous(expand = c(0, 0), label = ~ abs(.)) +
    guides(fill = guide_legend(reverse = TRUE)) +
    labs(fill = "") +
    theme_bw() +
    theme(axis.text.x = element_text(angle = -90, vjust = 0.5))


plot_with_pattern

shafee
  • 15,566
  • 3
  • 19
  • 47
  • 2
    `ggpattern` is now on CRAN, so you don't need to install from GitHub. You can simply do `install.packages("ggpattern")` – Allan Cameron Aug 14 '22 at 19:33
  • Owh! Thanks for pointing it out and for the edit. @AllanCameron. – shafee Aug 14 '22 at 19:41
  • Warning messages: 1: convert_polygon_sf_to_polygon_df(): Not POLYGON or MULTIPOLYGON: c("XY", "LINESTRING", "sfg") 2: convert_polygon_sf_to_polygon_df(): Not POLYGON or MULTIPOLYGON: c("XY", "LINESTRING", "sfg") 3: convert_polygon_sf_to_polygon_df(): Not POLYGON or MULTIPOLYGON: c("XY", "LINESTRING", "sfg") 4: convert_polygon_sf_to_polygon_df(): Not POLYGON or MULTIPOLYGON: c("XY", "LINESTRING", "sfg") 5: convert_polygon_sf_to_polygon_df(): Not POLYGON or MULTIPOLYGON: c("XY", "LINESTRING", "sfg") – Daniel James Aug 14 '22 at 20:41
  • Another issue is that only the last `key` shows in `legend`, the first three are mare squared boxes – Daniel James Aug 14 '22 at 20:44
  • Did you try as exactly what I did here?! Because As you can see in the plot its working for me. – shafee Aug 15 '22 at 02:21
  • Your output is not completely reproducible at my end and also at some peoples' end. Please see the code that you ran to get your output that is not in your answer here. – Daniel James Aug 15 '22 at 15:55
  • But I am still getting the same fine plot. Whats your `ggpattern` package version? mine is `‘0.4.3.3’`. Also I have added my full script that I am running to get this plot. – shafee Aug 15 '22 at 16:24