The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
Mangiola et al., (2020). tidyHeatmap: an R package for modular heatmap production based on tidy principles. Journal of Open Source Software, 5(52), 2472, https://doi.org/10.21105/joss.02472
tidyHeatmap is a package that introduces tidy principles
to the creation of information-rich heatmaps. This package uses ComplexHeatmap
as graphical engine. website: stemangiola.github.io/tidyHeatmap
Advantages:
annotation_group,
e.g. heatmap(...) |> annotation_group(...)| Function | Description |
|---|---|
heatmap |
Plots base heatmap |
annotation_group |
Adds group annotation strips and grouping to the heatmap (replaces group_by) |
annotation_tile |
Adds tile annotation to the heatmap |
annotation_point |
Adds point annotation to the heatmap |
annotation_bar |
Adds bar annotation to the heatmap |
annotation_numeric |
Adds bar + number annotation to the heatmap |
annotation_line |
Adds line annotation to the heatmap |
layer_text |
Add layer of text on top of the heatmap |
layer_point |
Adds layer of symbols on top of the heatmap |
layer_square |
Adds layer of symbols on top of the heatmap |
layer_diamond |
Adds layer of symbols on top of the heatmap |
layer_arrow_up |
Adds layer of symbols on top of the heatmap |
layer_arrow_down |
Add layer of symbols on top of the heatmap |
layer_star |
Add layer of symbols on top of the heatmap |
layer_asterisk |
Add layer of symbols on top of the heatmap |
split_rows |
Splits the rows based on the dendogram |
split_columns |
Splits the columns based on the dendogram |
save_pdf |
Saves the PDF of the heatmap |
+ |
Integrate heatmaps side-by-side |
as_ComplexHeatmap |
Convert the tidyHeatmap output to ComplexHeatmap for non-standard “drawing” |
wrap_heatmap |
Allows the integration with the patchwork package |
To install the most up-to-date version
To install the most stable version (however please keep in mind that this package is under a maturing lifecycle stage)
If you want to contribute to the software, report issues or problems with the software or seek support please open an issue here
The heatmaps visualise a multi-element, multi-feature dataset, annotated with independent variables. Each observation is a element-feature pair (e.g., person-physical characteristics).
| element | feature | value | independent_variables |
|---|---|---|---|
chr or fctr |
chr or fctr |
numeric |
… |
Let’s transform the mtcars dataset into a tidy “element-feature-independent variables” data frame. Where the independent variables in this case are ‘hp’ and ‘vs’.
mtcars_tidy <-
mtcars |>
as_tibble(rownames="Car name") |>
# Scale
mutate_at(vars(-`Car name`, -hp, -vs), scale) |>
# tidyfy
pivot_longer(cols = -c(`Car name`, hp, vs), names_to = "Property", values_to = "Value")
mtcars_tidy## # A tibble: 288 × 5
## `Car name` hp vs Property Value[,1]
## <chr> <dbl> <dbl> <chr> <dbl>
## 1 Mazda RX4 110 0 mpg 0.151
## 2 Mazda RX4 110 0 cyl -0.105
## 3 Mazda RX4 110 0 disp -0.571
## 4 Mazda RX4 110 0 drat 0.568
## 5 Mazda RX4 110 0 wt -0.610
## 6 Mazda RX4 110 0 qsec -0.777
## 7 Mazda RX4 110 0 am 1.19
## 8 Mazda RX4 110 0 gear 0.424
## 9 Mazda RX4 110 0 carb 0.735
## 10 Mazda RX4 Wag 110 0 mpg 0.151
## # ℹ 278 more rows
For plotting, you simply pipe the input data frame into heatmap, specifying:
mtcars
mtcars_heatmap <-
mtcars_tidy |>
heatmap(`Car name`, Property, Value, scale = "row" ) |>
annotation_tile(hp)## tidyHeatmap says: If you use tidyHeatmap for scientific research, please cite: Mangiola, S. and Papenfuss, A.T., 2020. 'tidyHeatmap: an R package for modular heatmap production based on tidy principles.' Journal of Open Source Software. doi:10.21105/joss.02472.
## This message is displayed once per session.
Choose alternative clustering distance and methods.
tidyHeatmap::pasilla |>
heatmap(
.column = sample,
.row = symbol,
.value = `count normalised adjusted`,
scale = "row",
# Arguments passed to ComplexHeatmap
clustering_distance_rows = "manhattan",
clustering_distance_columns = "manhattan",
clustering_method_rows = "ward.D",
clustering_method_columns = "ward.D"
) We can easily group the data (one group per dimension maximum, at the moment only the vertical dimension is supported) with dplyr, and the heatmap will be grouped accordingly
# Make up more groupings
mtcars_tidy_groupings =
mtcars_tidy |>
mutate(property_group = if_else(Property %in% c("cyl", "disp"), "Engine", "Other"))
mtcars_tidy_groupings |>
heatmap(`Car name`, Property, Value, scale = "row") |>
annotation_group(vs, property_group) |>
annotation_tile(hp)You can provide colour palettes and other aesthetics to groupings
mtcars_tidy_groupings |>
heatmap(
`Car name`, Property, Value ,
scale = "row"
) |>
annotation_group(
vs, property_group,
palette_grouping = list(
# For first grouping (vs)
c("#66C2A5", "#FC8D62"),
# For second grouping (property_group)
c("#b58b4c", "#74a6aa")
),
group_label_fontsize = 14,
show_group_name = TRUE,
group_strip_height = grid::unit(20, "pt")
) |>
annotation_tile(hp)We can split based on the cladogram
mtcars_tidy |>
heatmap(`Car name`, Property, Value, scale = "row" ) |>
split_rows(2) |>
split_columns(2)We can split on kmean clustering (using ComplexHeatmap options, it is stochastic)
We can easily use custom palette, using strings, hexadecimal color character vector,
mtcars_tidy |>
heatmap(
`Car name`,
Property,
Value,
scale = "row",
palette_value = c("red", "white", "blue")
)A better-looking blue-to-red palette
mtcars_tidy |>
heatmap(
`Car name`,
Property,
Value,
scale = "row",
palette_value = circlize::colorRamp2(
seq(-2, 2, length.out = 11),
RColorBrewer::brewer.pal(11, "RdBu")
)
)Or a grid::colorRamp2 function for higher flexibility
mtcars_tidy |>
heatmap(
`Car name`,
Property,
Value,
scale = "row",
palette_value = circlize::colorRamp2(c(-2, -1, 0, 1, 2), viridis::magma(5))
)We can use custom colors for tile annotation
mtcars_tidy |>
heatmap(
`Car name`,
Property,
Value,
scale = "row"
) |>
annotation_tile(
hp,
palette = c("red", "white", "blue")
)We can use grid::colorRamp2 function for tile annotation for specific color scales
mtcars_tidy |>
heatmap(
`Car name`,
Property,
Value,
scale = "row"
) |>
annotation_tile(
hp,
palette = circlize::colorRamp2(c(0, 100, 200, 300), viridis::magma(4))
)tidyHeatmap::pasilla |>
heatmap(
.column = sample,
.row = symbol,
.value = `count normalised adjusted`,
scale = "row"
) |>
annotation_group(location, type) |>
annotation_tile(condition) |>
annotation_tile(activation)Example with custom aesthetics for annotation_group
tidyHeatmap::pasilla |>
heatmap(
.column = sample,
.row = symbol,
.value = `count normalised adjusted`,
scale = "row"
) |>
annotation_group(
location, type,
group_label_fontsize = 12,
group_strip_height = grid::unit(15, "pt"),
show_group_name = FALSE
) |>
annotation_tile(condition) |>
annotation_tile(activation)Remove legends, adding aesthetics to annotations in a modular
fashion, using ComplexHeatmap arguments
tidyHeatmap::pasilla |>
heatmap(
.column = sample,
.row = symbol,
.value = `count normalised adjusted`,
scale = "row",
show_heatmap_legend = FALSE
) |>
annotation_tile(condition, show_legend = FALSE) |>
annotation_tile(activation, show_legend = FALSE)“tile”, “point”, “bar”, “line” and “numeric” are available
# Create some more data points
pasilla_plus <-
tidyHeatmap::pasilla |>
dplyr::mutate(activation_2 = activation, activation_3 = activation) |>
tidyr::nest(data = -sample) |>
dplyr::mutate(size = rnorm(n(), 4,0.5)) |>
dplyr::mutate(age = runif(n(), 50, 200)) |>
tidyr::unnest(data)
# Plot
pasilla_plus |>
heatmap(
.column = sample,
.row = symbol,
.value = `count normalised adjusted`,
scale = "row"
) |>
annotation_tile(condition) |>
annotation_point(activation) |>
annotation_numeric(activation_3) |>
annotation_tile(activation_2) |>
annotation_bar(size) |>
annotation_line(age)We can customise annotation sizes using the
grid::unit(), and the size of their names using in-built
ComplexHeatmap arguments
pasilla_plus |>
heatmap(
.column = sample,
.row = symbol,
.value = `count normalised adjusted`,
scale = "row"
) |>
annotation_tile(condition, size = unit(0.3, "cm"), annotation_name_gp= gpar(fontsize = 8)) |>
annotation_point(activation, size = unit(0.3, "cm"), annotation_name_gp= gpar(fontsize = 8)) |>
annotation_tile(activation_2, size = unit(0.3, "cm"), annotation_name_gp= gpar(fontsize = 8)) |>
annotation_bar(size, size = unit(0.3, "cm"), annotation_name_gp= gpar(fontsize = 8)) |>
annotation_line(age, size = unit(0.3, "cm"), annotation_name_gp= gpar(fontsize = 8))Add a layer on top of the heatmap
tidyHeatmap::pasilla |>
# filter
filter(symbol %in% head(unique(tidyHeatmap::pasilla$symbol), n = 10)) |>
# Add dynamic size
mutate(my_size = runif(n(), 1,5)) |>
heatmap(
.column = sample,
.row = symbol,
.value = `count normalised adjusted`,
scale = "row"
) |>
layer_point(
`count normalised adjusted log` > 6 & sample == "untreated3"
) |>
layer_square(
`count normalised adjusted log` > 6 & sample == "untreated2",
.size = my_size
) |>
layer_arrow_up(
`count normalised adjusted log` > 6 & sample == "untreated1",
.size = 4
)Advanced example showing different symbols with custom colors and sizes
tidyHeatmap::pasilla |>
# filter
filter(symbol %in% head(unique(tidyHeatmap::pasilla$symbol), n = 10)) |>
# Add dynamic color and size columns
mutate(
my_color = case_when(
`count normalised adjusted log` > 7 ~ "#57fb77",
`count normalised adjusted log` > 6 ~ "darkorange",
TRUE ~ "#fb7ef9"
),
my_size = runif(n(), 3, 8)
) |>
heatmap(
.column = sample,
.row = symbol,
.value = `count normalised adjusted`,
scale = "row"
) |>
layer_point(
`count normalised adjusted log` > 6 & sample == "untreated3",
.color = "red",
.size = 5
) |>
layer_diamond(
`count normalised adjusted log` > 6 & sample == "untreated1",
.color = "green",
.size = 6
) |>
layer_star(
`count normalised adjusted log` > 7,
.color = "purple",
.size = 4
) |>
# Dynamically color and size
layer_square(
`count normalised adjusted log` > 6 & sample == "untreated2",
.color = my_color,
.size = my_size
)Add a text layer on top of the heatmap
tidyHeatmap::pasilla |>
# filter
filter(symbol %in% head(unique(tidyHeatmap::pasilla$symbol), n = 10)) |>
# Add dynamic text
mutate(my_text = "mt", my_size = 7) |>
# Plot
heatmap(
.column = sample,
.row = symbol,
.value = `count normalised adjusted`,
scale = "row"
) |>
layer_text(
`count normalised adjusted log` > 6 & sample == "untreated3",
.value = "a",
.size = 15
) |>
layer_text(
`count normalised adjusted log` > 6 & sample == "untreated2",
.value = my_text,
.size = my_size
)Advanced example showing text layers with custom colors, sizes, and dynamic content
tidyHeatmap::pasilla |>
# filter
filter(symbol %in% head(unique(tidyHeatmap::pasilla$symbol), n = 10)) |>
# Add dynamic text content and styling
mutate(
text_content = case_when(
`count normalised adjusted log` > 7 ~ "***",
`count normalised adjusted log` > 6 ~ "**",
`count normalised adjusted log` > 5 ~ "*",
TRUE ~ ""
),
text_color = case_when(
`count normalised adjusted log` > 7 ~ "darkred",
`count normalised adjusted log` > 6 ~ "darkorange",
`count normalised adjusted log` > 5 ~ "darkgreen",
TRUE ~ "darkgray"
),
text_size = case_when(
`count normalised adjusted log` > 7 ~ 12,
`count normalised adjusted log` > 6 ~ 10,
`count normalised adjusted log` > 5 ~ 8,
TRUE ~ 6
)
) |>
heatmap(
.column = sample,
.row = symbol,
.value = `count normalised adjusted`,
scale = "row"
) |>
layer_text(
`count normalised adjusted log` > 6 & sample == "untreated3",
.value = "HIGH",
.color = "red",
.size = 12
) |>
layer_text(
`count normalised adjusted log` > 5 & sample == "untreated1",
.value = "↑",
.color = "blue",
.size = 10
) |>
# Dynamically set text content, color and size
layer_text(
`count normalised adjusted log` > 6 & sample == "untreated2",
.value = text_content,
.color = text_color,
.size = text_size
)Add more than two heatmaps
Note:
Due to limitations in R’s method dispatch, adding more than two tidyHeatmap heatmaps using the
+operator (e.g.p_heatmap + p_heatmap + p_heatmap) may result in an error or unexpected behavior.To robustly combine more than two heatmaps, convert each to a ComplexHeatmap object first, this will use the
+functionality ofComplexHeatmap. This ensures that all objects are compatible and can be combined using ComplexHeatmap’s native addition functionality.
## Warning: package 'ggplot2' was built under R version 4.5.1
## Warning: package 'patchwork' was built under R version 4.5.1
p_heatmap =
mtcars_tidy |>
heatmap(
`Car name`, Property, Value,
scale = "row",
show_heatmap_legend = FALSE,
row_names_gp = gpar(fontsize = 7)
)
p_ggplot = data.frame(value = 1:10) |> ggplot(aes(value)) + geom_density()
wrap_heatmap(p_heatmap) +
p_ggplot +
# Add padding for better aesthetics
wrap_heatmap(
p_heatmap,
padding = grid::unit(c(-30, -0, -0, -10), "points" ),
clip = FALSE
) +
plot_layout(width = c(1, 0.3, 1))mtcars_tidy |>
heatmap(
`Car name`, Property, Value,
scale = "row",
rect_gp = grid::gpar(col = "#161616", lwd = 0.5)
) ## Warning: package 'forcats' was built under R version 4.5.1
mtcars_tidy |>
mutate(`Car name` = forcats::fct_reorder(`Car name`, `Car name`, .desc = TRUE)) %>%
heatmap(
`Car name`, Property, Value,
scale = "row",
cluster_rows = FALSE
) mtcars_tidy |>
mutate(`Car name` = forcats::fct_reorder(`Car name`, `Car name`, .desc = TRUE)) %>%
heatmap(
`Car name`, Property, Value,
scale = "row",
column_dend_height = unit(0.2, "cm"),
row_dend_width = unit(0.2, "cm")
) mtcars_tidy |>
mutate(`Car name` = forcats::fct_reorder(`Car name`, `Car name`, .desc = TRUE)) %>%
heatmap(
`Car name`, Property, Value,
scale = "row",
row_names_gp = gpar(fontsize = 7),
column_names_gp = gpar(fontsize = 7),
column_title_gp = gpar(fontsize = 7),
row_title_gp = gpar(fontsize = 7)
) You can completely remove the row and column titles by setting them to empty strings:
mtcars_tidy |>
mutate(`Car name` = forcats::fct_reorder(`Car name`, `Car name`, .desc = TRUE)) |>
heatmap(
`Car name`, Property, Value,
scale = "row",
row_title = "", # Remove row title
column_title = "" # Remove column title
) This can be done only for annotation_numeric because of
ComplexHeatmap requirements
(?ComplexHeatmap::anno_numeric)
mtcars_tidy |>
mutate(`Car name` = forcats::fct_reorder(`Car name`, `Car name`, .desc = TRUE)) %>%
heatmap(
`Car name`, Property, Value,
scale = "row"
) |>
annotation_numeric(hp, align_to="right")ComplexHeatmap functionalitiesComplexHeatmap has some graphical functionalities that are not
included in the standard functional framework. We can use
as_ComplexHeatmap to convert our output before applying
drawing options.
heatmap(mtcars_tidy, `Car name`, Property, Value, scale = "row" ) %>%
as_ComplexHeatmap() %>%
ComplexHeatmap::draw(heatmap_legend_side = "left" )## R version 4.5.0 (2025-04-11)
## Platform: x86_64-apple-darwin20
## Running under: macOS Sonoma 14.6.1
##
## Matrix products: default
## BLAS: /Library/Frameworks/R.framework/Versions/4.5-x86_64/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.5-x86_64/Resources/lib/libRlapack.dylib; LAPACK version 3.12.1
##
## locale:
## [1] C/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
##
## time zone: Australia/Adelaide
## tzcode source: internal
##
## attached base packages:
## [1] grid stats graphics grDevices utils datasets methods
## [8] base
##
## other attached packages:
## [1] forcats_1.0.1 patchwork_1.3.2 ggplot2_4.0.0 tidyHeatmap_1.13.1
## [5] tidyr_1.3.1 dplyr_1.1.4
##
## loaded via a namespace (and not attached):
## [1] viridis_0.6.5 utf8_1.2.6 sass_0.4.10
## [4] generics_0.1.4 shape_1.4.6.1 digest_0.6.37
## [7] magrittr_2.0.4 evaluate_1.0.5 RColorBrewer_1.1-3
## [10] iterators_1.0.14 circlize_0.4.16 fastmap_1.2.0
## [13] foreach_1.5.2 doParallel_1.0.17 jsonlite_2.0.0
## [16] GlobalOptions_0.1.2 gridExtra_2.3 ComplexHeatmap_2.25.2
## [19] purrr_1.1.0 viridisLite_0.4.2 scales_1.4.0
## [22] codetools_0.2-20 jquerylib_0.1.4 cli_3.6.5
## [25] rlang_1.1.6 crayon_1.5.3 withr_3.0.2
## [28] cachem_1.1.0 yaml_2.3.10 tools_4.5.0
## [31] parallel_4.5.0 colorspace_2.1-2 GetoptLong_1.0.5
## [34] BiocGenerics_0.55.4 vctrs_0.6.5 R6_2.6.1
## [37] png_0.1-8 magick_2.9.0 matrixStats_1.5.0
## [40] stats4_4.5.0 lifecycle_1.0.4 S4Vectors_0.47.4
## [43] IRanges_2.43.5 clue_0.3-66 cluster_2.1.8.1
## [46] dendextend_1.19.1 pkgconfig_2.0.3 gtable_0.3.6
## [49] pillar_1.11.1 bslib_0.9.0 Rcpp_1.1.0
## [52] glue_1.8.0 xfun_0.53 tibble_3.3.0
## [55] tidyselect_1.2.1 rstudioapi_0.17.1 knitr_1.50
## [58] farver_2.1.2 rjson_0.2.23 htmltools_0.5.8.1
## [61] labeling_0.4.3 rmarkdown_2.30 Cairo_1.6-5
## [64] compiler_4.5.0 S7_0.2.0
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.