TeriyakiNinja
TeriyakiNinja

Reputation: 13

Adding separations and bottom annotation in geom_tile ggplot

So I created a heatmap using geom_tile() as follows:

df_temp <- df_master
df_temp$X <- c(1:length(df_master$CHR))
df_temp[ ,c('CHR')] <- list(NULL)
df_temp <- melt(df_temp, id.vars="X")

n1 <- length(unique(df_temp$variable))
n2 <- length(unique(df_temp$X))

ggplot(df_temp, aes(x = X, y = variable, fill = value)) +
  theme(axis.title.x = element_blank()) +
  theme(axis.ticks.x = element_blank(),
        axis.text.x = element_blank())  +
  geom_tile() + 
  scale_fill_gradientn(
            colors=c("grey","orange","dark red"), na.value="grey",
            values=rescale(c(0,5,40)),
            limits=c(0,40)) +
  geom_line(data = data.frame(x = c(0, n2) + 0.5, y = rep(2:n1, each = 2) - 0.5),
            aes(x = x, y = y, group = y), size=1, colour = 'white', inherit.aes = FALSE)

This produced the following heatmap.

However, the x-axis has a subcategory that groups each observation from 1-20 and is ordered appropriately. I want this to be reflected in the ggplot somehow, with a bottom annotation and maybe some separations inside the heatmap? Excuse my mouse painting skills but something like this:

So the bottom annotation should be like a single-row colour map that indicates which group the above observations fall under. The black lines would signify exact locations at which these groups are separate.

Is this possible? I've tried going through the internet, but have yet to find a clear answer. Thank you!

EDIT: Forgot to add what df_temp looks like!

> df_temp
      X                variable      value    CHR
1     1                       A  0.3432559 M.m.01
2     2                       A  0.3675018 M.m.02
3     3                       A  0.8010609 M.m.06
4     4                       A  1.3608854 M.m.10
5     5                       A  0.3369016 M.m.13
6     6                       B  1.3765413 M.m.02
7     7                       B  1.5141245 M.m.03
8     8                       B  0.8467624 M.m.05
9     9                       B  0.7612501 M.m.07
10   10                       B  0.8377142 M.m.10
11   11                       B  0.4613787 M.m.13
12   12                       B  1.4047240 M.m.16
13   13                       B  0.9338802 M.m.19
14   14                       B  1.1825244 M.m.20
15   15                       C  0.3156074 M.m.01
16   16                       C  2.3541151 M.m.02
17   17                       C  2.3725061 M.m.05
18   18                       C  1.5970541 M.m.10
19   19                       D  0.3901532 M.m.01
20   20                       D  0.3156074 M.m.02
21   21                       D  2.9405363 M.m.03
22   22                       E  1.5055971 M.m.07
23   23                       E  1.8618063 M.m.08
24   24                       F  0.7314612 M.m.02
25   25                       F  0.7705067 M.m.03

Where CHR ranges from M.m.01 to M.m.20 and variable ranges from 6 different categories. This is the result after melt().

Upvotes: 0

Views: 1699

Answers (1)

Allan Cameron
Allan Cameron

Reputation: 173858

This can be done with themed facets using the ggh4x package.

The sample data provided doesn't really reproduce your plot, so I have created my own with the same structure for illustration purposes.

library(ggh4x)

ggplot(df_temp, aes(x = X, y = variable, fill = value)) +
  geom_tile() +
  geom_hline(yintercept = 0:6 + 0.5, color = "white") +
  scale_x_continuous(expand = c(0.01, 0)) +
  scale_fill_gradientn(
            colors=c("grey","orange","dark red"), na.value="grey",
            values=scales::rescale(c(0,5,40)),
            limits=c(0,40)) +
  facet_grid2(.~CHR, scales = "free_x", space = "free_x", switch = "x",
              strip = strip_themed(
                background_x = elem_list_rect(
                  fill = rainbow(length(unique(df_temp$CHR)))))) +
  theme_bw(base_size = 16) +
  theme(axis.title.x     = element_blank(),
        axis.ticks.x     = element_blank(),
        axis.text.x      = element_blank(),
        panel.spacing.x  = unit(0, "mm"),
        panel.background = element_rect(fill = NA, color = "black", size = 1),
        panel.grid       = element_blank())

enter image description here


Data used

set.seed(1)

df_temp <- data.frame(X = rep(1:25, 6),
                      variable = rep(LETTERS[1:6], each = 25),
                      value = runif(25 * 6, 0, 2),
                      CHR = rep(paste("CHR", 
                                      rep(1:5, times = c(6, 4, 3, 7, 5))), 6))

Upvotes: 1

Related Questions