zesla
zesla

Reputation: 11793

Add a gap in heatmap with pheatmap package

I made the heatmap using the code below:

library(pheatmap)
library(dplyr)

data = data.frame(matrix(runif(10*10), ncol=10))
data$sample = rep(c("tumour", "normal"), 5)
data$subject.ID = paste('Subject', 1:10)
data = data %>% arrange(sample)

# for row annotation
my_sample_col = data %>% select(sample)
rownames(my_sample_col) = data$subject.ID
# data matrix
mat = as.matrix(data %>% select(-sample, -subject.ID))
rownames(mat) = data$subject.ID

pheatmap(mat,
         scale='row',
         annotation_row = my_sample_col,
         annotation_names_row=F,
         cluster_rows = FALSE,
         cluster_cols = FALSE,
         show_colnames = FALSE,
         show_rownames = FALSE)

I want to put a gap between row 5 and row 6, to separate the heatmap according to my row annotation.

In pheatmap function, the argument gaps_row seems to do the job.

vector of row indices that show shere to put gaps into heatmap. Used only if the rows are not clustered.

I'm not sure how to implement that. Can someone help me with this? Thanks a lot.

Upvotes: 1

Views: 17182

Answers (2)

SamGG
SamGG

Reputation: 71

When sample is not sorted, the previous snippet should be replaced by which(diff(as.numeric(factor(my_sample_col$sample)))!=0).

library(pheatmap)

# each row is a sample
# row annotation
row_annot = data.frame(
  sample = rep(c("tumour", "normal", "control"), times = c(4, 5, 1)),
  row.names = paste('Subject', 1:10))
# data matrix
mat = matrix(round(runif(10*20),2), nrow = 10)
rownames(mat) = row.names(row_annot)
# identify changes in sample vector
gp_row = which(diff(as.numeric(factor(row_annot$sample)))!=0)
pheatmap(
  mat,
  annotation_row = row_annot, annotation_names_row=F, gaps_row = gp_row,
  cluster_rows = FALSE, cluster_cols = FALSE
)
# original snippet
head(as.numeric(cumsum(table(row_annot$sample))), -1)

enter image description here

Upvotes: 0

pogibas
pogibas

Reputation: 28329

I would recommend using ComplexHeatmap package (website; Gu et al, 2016). You can install it with devtools::install_github("jokergoo/ComplexHeatmap").

It has more functionalities, but you also have to invest more time (eg., row annotation and matrix scaling).

library(ComplexHeatmap)

# Create annotation for rows
my_sample_col_ano <- rowAnnotation(sample = my_sample_col$sample,
                                   show_annotation_name = FALSE)

# Scale original matrix row-wise
matS <- t(apply(mat, 1, scale))

# Plot heatmap
Heatmap(matS, 
        # Remove name from fill legend
        name = "",
        # Keep original row/col order
        row_order = rownames(matS), column_order = colnames(matS),
        # Add left annotation (legend with tumor/normal) 
        left_annotation = my_sample_col_ano,
        # ACTUAL SPLIT by sample group 
        row_split = my_sample_col$sample,
        show_row_names = FALSE, show_column_names = FALSE,
        show_row_dend = FALSE, show_column_dend = FALSE,
        row_title = NULL)

enter image description here

If you want to use original pheatmap pass argument to gaps_row which is equal to the size of your group (ie, normal):

pheatmap(mat,
         scale='row',
         gaps_row = 5,
         annotation_row = my_sample_col,
         annotation_names_row=F,
         cluster_rows = FALSE,
         cluster_cols = FALSE,
         show_colnames = FALSE,
         show_rownames = FALSE)

If you can more groups than two instead of hardcoding numeric value to gaps_row (ie, gaps_row = 5) you can pass this snippet (head(as.numeric(cumsum(table(my_sample_col$sample))), -1)).

enter image description here

Upvotes: 5

Related Questions