Add pch to rowAnnotation when the input is a data frame with variable number of continuous columns
Following up on this question, I am using ComplexHeatmap
inside a function that takes as input the variable names that I want to study.
While before I found trouble with the discrete grouping of my columns, now the problem is different. I want to plot additional continuous columns (stored in a different data frame) with significance *
(as pch) associated to them.
I normally know how to do this with rowAnnotation
and anno_simple
, but in this case (of ComplexHeatmap
inside a function), where I do not know the names (or the number!) of the extra columns to add, I have no clue.
I was hoping the answer to the previous question would apply to this too, and I almost got it, but still not quite there yet...
The following is my MWE.
I first define my inputs, the heatmap matrix heat_mat
, the extra_df
with the extra columns to add, and the color palettes to apply:
data(iris)
extra_cols <- c('zscore1', 'zscore2') #they can be 1, 2, 3... n
extra_pch <- c('pvalue1','pvalue2') #they can be 1, 2, 3... n
iris_sub <- rbind(iris[iris[,'Species']=='setosa',][1:5,],
iris[iris[,'Species']=='versicolor',][1:5,],
iris[iris[,'Species']=='virginica',][1:5,])
heat_mat <- as.matrix(iris_sub[,-ncol(iris_sub)])
#
extra_df <- data.frame(ID=paste0("id",rownames(iris_sub)))
for (i in 1:length(extra_cols)){
edf <- data.frame(VAR=rnorm(15))
names(edf) <- extra_cols[i]
pdf <- data.frame(VAR=runif(15, 0, 0.2))
pdf$VAR <- ifelse(pdf$VAR<0.05, '*', NA)
names(pdf) <- extra_pch[i]
extra_df <- cbind(extra_df, edf, pdf)
}
rownames(heat_mat) <- extra_df$ID
#
palette1 <- RColorBrewer::brewer.pal(n=9, name="RdYlGn")
palette2 <- RColorBrewer::brewer.pal(n=9, name="RdYlBu")
#
cols_list <- list()
for (nm in extra_cols){
breaks <- seq(from=min(extra_df[,nm]), to=max(extra_df[,nm]), length.out=length(palette2))
cols <- circlize::colorRamp2(breaks, palette2)
cols_list <- append(cols_list, cols)
names(cols_list)[length(cols_list)] <- nm
}
Now I would know how to do the heat map normally with rowAnnotation
and anno_simple
, like this:
row_ha <- ComplexHeatmap::rowAnnotation(
zscore1 = ComplexHeatmap::anno_simple(
extra_df[,extra_cols[1]], col = cols_list[[extra_cols[1]]],
pch = extra_df[,extra_pch[1]]),
zscore2 = ComplexHeatmap::anno_simple(
extra_df[,extra_cols[2]], col = cols_list[[extra_cols[2]]],
pch = extra_df[,extra_pch[2]]))
#
complex_heat <- ComplexHeatmap::Heatmap(heat_mat, name = "value", cluster_columns = FALSE,
col = palette1,
right_annotation = row_ha,
border = TRUE)
grDevices::png(filename="test.png", height=600, width=400)
ComplexHeatmap::draw(complex_heat)
grDevices::dev.off()
This produces the following plot, which is exactly what I need (not worried about the absence of legends for this example):
However, as stated before, in my current case (of ComplexHeatmap
inside a function), I do not know the names (or the number!) of the extra columns to add.
I would like to add a variable number of continuous columns with their associated pch as rowAnnotation
, for which the names are stored in 2 variables.
This is my best attempt (applying the answer to the previous question), but with this approach I cannot pass pch
.
row_df <- extra_df[,extra_cols,drop=F]
row_pch <- extra_df[,extra_pch,drop=F]
row_ha <- ComplexHeatmap::rowAnnotation(
df = row_df,
col = cols_list,
#pch = row_pch,
show_legend = FALSE)
#
complex_heat <- ComplexHeatmap::Heatmap(heat_mat, name = "value", cluster_columns = FALSE,
col = palette1,
right_annotation = row_ha,
border = TRUE)
grDevices::png(filename="test2.png", height=600, width=400)
ComplexHeatmap::draw(complex_heat)
grDevices::dev.off()
This produces the following plot, identical to the previous, but without the *
which I need... Any idea how to proceed?
Answers
To add the pch
(plotting characters) associated with the continuous columns as row annotations in ComplexHeatmap, you can use the anno_points
function instead of anno_simple
. anno_points
allows you to specify the pch
parameter, which determines the plotting character.
Here's how you can modify your code to achieve this:
library(ComplexHeatmap)
library(RColorBrewer)
# Define inputs
data(iris)
extra_cols <- c('zscore1', 'zscore2')
extra_pch <- c('pvalue1','pvalue2')
iris_sub <- rbind(iris[iris[,'Species']=='setosa',][1:5,],
iris[iris[,'Species']=='versicolor',][1:5,],
iris[iris[,'Species']=='virginica',][1:5,])
heat_mat <- as.matrix(iris_sub[,-ncol(iris_sub)])
extra_df <- data.frame(ID=paste0("id",rownames(iris_sub)))
for (i in 1:length(extra_cols)){
edf <- data.frame(VAR=rnorm(15))
names(edf) <- extra_cols[i]
pdf <- data.frame(VAR=runif(15, 0, 0.2))
pdf$VAR <- ifelse(pdf$VAR<0.05, '*', NA)
names(pdf) <- extra_pch[i]
extra_df <- cbind(extra_df, edf, pdf)
}
rownames(heat_mat) <- extra_df$ID
# Generate color palettes
palette1 <- RColorBrewer::brewer.pal(n=9, name="RdYlGn")
palette2 <- RColorBrewer::brewer.pal(n=9, name="RdYlBu")
cols_list <- list()
for (nm in extra_cols){
breaks <- seq(from=min(extra_df[,nm]), to=max(extra_df[,nm]), length.out=length(palette2))
cols <- circlize::colorRamp2(breaks, palette2)
cols_list <- append(cols_list, cols)
names(cols_list)[length(cols_list)] <- nm
}
# Create row annotation with plotting characters
row_df <- extra_df[, extra_cols, drop = FALSE]
row_pch <- extra_df[, extra_pch, drop = FALSE]
row_ha <- rowAnnotation(
df = row_df,
col = cols_list,
pch = row_pch, # Add pch parameter here
show_legend = FALSE
)
# Create heatmap
complex_heat <- Heatmap(
heat_mat, name = "value", cluster_columns = FALSE,
col = palette1,
right_annotation = row_ha,
border = TRUE
)
# Draw heatmap
grDevices::png(filename="test.png", height=600, width=400)
draw(complex_heat)
grDevices::dev.off()
With anno_points
, you can specify the plotting characters using the pch
parameter, which will allow you to add the '*' as required. This should produce the desired heatmap with the required plotting characters.