How to Add Hatches, Stripes or Another Pattern or Texture to a Barplot in Ggplot

How can I add hatches, stripes or another pattern or texture to a barplot in ggplot?

One approach is to use the ggpattern package written by Mike FC (no affiliation):

library(ggplot2)
#remotes::install_github("coolbutuseless/ggpattern")
library(ggpattern)
ggplot(data = df, aes(x = Class, fill = StudyTime, pattern = Nerd)) +
geom_bar_pattern(position = position_dodge(preserve = "single"),
color = "black",
pattern_fill = "black",
pattern_angle = 45,
pattern_density = 0.1,
pattern_spacing = 0.025,
pattern_key_scale_factor = 0.6) +
scale_fill_manual(values = colorRampPalette(c("#0066CC","#FFFFFF","#FF8C00"))(4)) +
scale_pattern_manual(values = c(Nerd = "stripe", NotNerd = "none")) +
labs(x = "Class", y = "Number of Students", pattern = "Nerd?") +
guides(pattern = guide_legend(override.aes = list(fill = "white")),
fill = guide_legend(override.aes = list(pattern = "none")))

Sample Image

The package appears to support a number of common geometries. Here is an example of using geom_tile to combine a continuous variable with a categorical variable:

set.seed(40)
df2 <- data.frame(Row = rep(1:9,times=9), Column = rep(1:9,each=9),
Evaporation = runif(81,50,100),
TreeCover = sample(c("Yes", "No"), 81, prob = c(0.3,0.7), replace = TRUE))

ggplot(data=df2, aes(x=as.factor(Row), y=as.factor(Column),
pattern = TreeCover, fill= Evaporation)) +
geom_tile_pattern(pattern_color = NA,
pattern_fill = "black",
pattern_angle = 45,
pattern_density = 0.5,
pattern_spacing = 0.025,
pattern_key_scale_factor = 1) +
scale_pattern_manual(values = c(Yes = "circle", No = "none")) +
scale_fill_gradient(low="#0066CC", high="#FF8C00") +
coord_equal() +
labs(x = "Row",y = "Column") +
guides(pattern = guide_legend(override.aes = list(fill = "white")))

Sample Image

Adding hatches or patterns to ggplot bars

Following the linked answer, it seems quite natural how to extend it to your case. In the example below, I'm using some dummy data structured like the head() data you gave, since the csv link gave me a 404.

library(ggplot2)
library(ggpattern)
#>
#> Attaching package: 'ggpattern'
#> The following objects are masked from 'package:ggplot2':
#>
#> flip_data, flipped_names, gg_dep, has_flipped_aes, remove_missing,
#> should_stop, waiver

# Setting up some dummy data
set.seed(42)
f1 <- expand.grid(
comp = LETTERS[1:3],
exp = c("qPCR", "RNA-seq"),
geneID = paste("Gene", 1:4)
)
f1$logfc <- rnorm(nrow(f1))

ggplot(f1, aes(x = geneID, y = logfc, fill = comp)) +
geom_col_pattern(
aes(pattern = exp),
colour = "black",
pattern_fill = "black",
pattern_angle = 45,
pattern_density = 0.1,
pattern_spacing = 0.01,
position = position_dodge2(preserve = 'single'),
) +
scale_pattern_manual(
values = c("none", "stripe"),
guide = guide_legend(override.aes = list(fill = "grey70")) # <- make lighter
) +
scale_fill_discrete(
guide = guide_legend(override.aes = list(pattern = "none")) # <- hide pattern
)

Sample Image

Created on 2021-04-19 by the reprex package (v1.0.0)

EDIT: if you want to repeat the hatching in the fill legend, you can make an interaction() and then customise a manual fill scale.

ggplot(f1, aes(x = geneID, y = logfc)) +
geom_col_pattern(
aes(pattern = exp,
fill = interaction(exp, comp)), # <- make this an interaction
colour = "black",
pattern_fill = "black",
pattern_angle = 45,
pattern_density = 0.1,
pattern_spacing = 0.01,
position = position_dodge2(preserve = 'single'),
) +
scale_pattern_manual(
values = c("none", "stripe"),
guide = guide_legend(override.aes = list(fill = "grey70")) # <- make lighter
) +
scale_fill_manual(
# Have 3 colours and repeat each twice
values = rep(scales::hue_pal()(3), each = 2),
# Extract the second name after the '.' from the `interaction()` call
labels = function(x) {
vapply(strsplit(x, "\\."), `[`, character(1), 2)
},
# Repeat the pattern over the guide
guide = guide_legend(
override.aes = list(pattern = rep(c("none", "stripe"), 3))
)
)

Sample Image

Created on 2021-04-19 by the reprex package (v1.0.0)

EDIT2: Now with errorbars:

library(ggplot2)
library(ggpattern)
set.seed(42)

f1 <- expand.grid(
comp = LETTERS[1:3],
exp = c("qPCR", "RNA-seq"),
geneID = paste("Gene", 1:4)
)
f1$logfc <- rnorm(nrow(f1))
f1$SE <- runif(nrow(f1), min=0, max=1.5)

ggplot(f1, aes(x = geneID, y = logfc)) +
geom_col_pattern(
aes(pattern = exp,
fill = interaction(exp, comp)), # <- make this an interaction
colour = "black",
pattern_fill = "black",
pattern_angle = 45,
pattern_density = 0.1,
pattern_spacing = 0.01,
position = position_dodge2(preserve = 'single'),
) +
geom_errorbar(
aes(
ymin = logfc,
ymax = logfc + sign(logfc) * SE,
group = interaction(geneID, comp, exp)
),
position = "dodge"
) +
scale_pattern_manual(
values = c("none", "stripe"),
guide = guide_legend(override.aes = list(fill = "grey70")) # <- make lighter
) +
scale_fill_manual(
# Have 3 colours and repeat each twice
values = rep(scales::hue_pal()(3), each = 2),
# Extract the second name after the '.' from the `interaction()` call
labels = function(x) {
vapply(strsplit(x, "\\."), `[`, character(1), 2)
},
# Repeat the pattern over the guide
guide = guide_legend(
override.aes = list(pattern = rep(c("none", "stripe"), 3))
)
)

Sample Image

Created on 2021-04-22 by the reprex package (v1.0.0)

ggplot2: Add Different Textures to Colored Barplot and Legend

I was able to solve this using ggpattern

# remotes::install_github("coolbutuseless/ggpattern")
library(ggpattern)
library(ggplot2)

data_ggp <- data.frame(category = rep(c("cat1", "cat2", "cat3"), 4),
values = c(0.664, 0.045, 0.291, 0.482, 0.029, 0.489, 0.537, 0.027, 0.436, 0.536, 0.028, 0.436),
group = c(rep("group1a", 3), rep("group1b", 3), rep("group2a", 3), rep("group2b", 3)))

ggplot(data_ggp, aes(category, values)) +
geom_bar_pattern(stat = "identity",
pattern = c("none", "none", "none", # 1st col
"none", "none", "none", # 2nd col
"stripe", "stripe", "stripe", # 3rd col
"crosshatch", "crosshatch", "crosshatch" # 4th col
),
pattern_angle = c(rep(0, 6), rep(45, 3), rep(0, 3)),
pattern_density = .1,
pattern_spacing = .04,
pattern_fill = 'black',
aes(fill = group),
position = "dodge") +
scale_fill_manual(" ",
labels = c("group1a", "group1b", "group2a", "group2b"),
values = c("group1a" = "deepskyblue4", "group1b" = "darkolivegreen4",
"group2a" = "deepskyblue1", "group2b" = "darkolivegreen2")) +
guides(fill = guide_legend(override.aes =
list(
pattern = c("none", "none", "stripe", "crosshatch"),
pattern_spacing = .01,
pattern_angle = c(0, 0, 45, 0)
)
))

Sample Image

Created on 2021-01-13 by the reprex package (v0.3.0)

How to add texture to fill colors in ggplot2

ggplot can use colorbrewer palettes. Some of these are "photocopy" friendly. So mabe something like this will work for you?

ggplot(diamonds, aes(x=cut, y=price, group=cut))+
geom_boxplot(aes(fill=cut))+scale_fill_brewer(palette="OrRd")

in this case OrRd is a palette found on the colorbrewer webpage: http://colorbrewer2.org/

Photocopy Friendly: This indicates
that a given color scheme will
withstand black and white
photocopying. Diverging schemes can
not be photocopied successfully.
Differences in lightness should be
preserved with sequential schemes.

How to position overlapping bar plot and bar width manually?

How about something like this:

d1 <- c(1.0, 2.0, 3.0, 4.0, 4.8)
d2 <- c(0.15, 0.5, 1.0, 1.5, 3.3)
d3 <- c(0.16,0.7,0.7,1,2.5)

df <- data.frame(d1, d2, d3)

library(dplyr)
library(ggplot2)

df %>%
mutate(index = seq_along(d1)) %>%
ggplot() +
geom_col(
aes(x = index, y = d1),
width = 0.8,
col = "black",
fill = "forestgreen"
) +
geom_col(
aes(x = index, y = d2),
width = 0.4,
col = "black",
fill = "red",
position = ggplot2::position_nudge(x = 0.2)
) +
geom_col(
aes(x = index, y = d3),
width = 0.4,
col = "black",
fill = "blue",
position = ggplot2::position_nudge(x = -0.2)
) +
labs(y = NULL)

Sample Image

Created on 2022-03-30 by the reprex package (v2.0.1)

Update: patterns instead of colors

This is actually not straightforward with ggplot2 itself. If you're OK with downloading packages outside CRAN then you can download ggpattern and do something like this:

df %>%
mutate(index = seq_along(d1)) %>%
ggplot() +
geom_col(
aes(x = index, y = d1),
width = 0.8,
col = "black",
fill = "forestgreen"
) +
ggpattern::geom_col_pattern(
aes(x = index, y = d2),
width = 0.4,
color = "black",
fill = "white",
pattern = 'stripe',
pattern_size = 0.1,
pattern_fill = "black",
position = ggplot2::position_nudge(x = 0.2)
) +
ggpattern::geom_col_pattern(
aes(x = index, y = d3),
width = 0.4,
color = "black",
fill = "lightgray",
pattern = 'crosshatch',
pattern_fill = "black",
pattern_angle = 0,
pattern_size = 0.1,
position = ggplot2::position_nudge(x = -0.2)
) +
labs(y = NULL)

Sample Image

Created on 2022-03-31 by the reprex package (v2.0.1)

ggpattern is well documented, so you should be able to adjust the above example to your needs.

If you don't want to rely on packages outside CRAN then you can take a look at any of these old questions for possible workarounds:

  • How to add texture to fill colors in ggplot2
  • Adding hatches or patterns to ggplot bars
  • ggplot2: Add Different Textures to Colored Barplot and Legend
  • How can I add hatches, stripes or another pattern or texture to a barplot in ggplot?


Related Topics



Leave a reply



Submit