Skip to main content
v2026.11,858 entries · CC-BY 4.0

Heatmap in R: heatmap(), pheatmap and ggplot2

Make a heatmap in R with base heatmap(), pheatmap or ggplot2 geom_tile, including a correlation heatmap and the scaling and NA settings that change it.

Written and maintained by CASRAI Editorial Board

Last updated

A heatmap in R colours the cells of a matrix by value, so patterns across many rows and columns show at a glance. You can draw one with three routes: the base heatmap() function in the stats package, pheatmap() from the pheatmap package, or geom_tile() in ggplot2. The choice matters less than three settings that change what the colours mean: scaling, clustering and, for correlation heatmaps, how cor() treats missing values.

What a heatmap is used for in research

Researchers use heatmaps to show a table of numbers as colour: expression levels across samples, a correlation matrix among variables, or counts across categories. Clustered heatmaps add dendrograms so similar rows and columns sit together. For the wider figure rules that apply once the plot is made, see designing effective scientific figures and scientific figure rules for journal submission.

Install or access (official sources only)

The base heatmap() function belongs to the stats package, which is part of a standard R installation, so nothing needs installing. The other two routes use CRAN packages:

install.packages("pheatmap")
install.packages("ggplot2")

If you are new to the R environment itself, how to use RStudio covers the interface.

Step-by-step: how to make a heatmap in R

The examples use mtcars, a data set that ships with R, so they run without any file.

Step 1. Base R: heatmap()

  1. Convert the data to a numeric matrix: x <- as.matrix(mtcars).
  2. Draw it: heatmap(x, scale = "column").

The scale argument accepts "row", "column" or "none". Its default is "row" when symm is false and "none" otherwise. Scaling affects only the colour scale, not the underlying data. In the mtcars example the columns are different measurements on different units, which is why column scaling is chosen.

By default heatmap() reorders rows and columns using hierarchical clustering (distfun = dist, hclustfun = hclust) and draws the dendrograms. Setting Rowv = NA suppresses the row dendrogram and reordering, which keeps your rows in their original order.

Step 2. pheatmap()

  1. Load the package: library(pheatmap).
  2. Draw it: pheatmap(as.matrix(mtcars), scale = "column").

pheatmap() is documented as a function to draw clustered heatmaps. Its defaults are scale = "none", cluster_rows = TRUE, cluster_cols = TRUE, clustering_distance_rows and clustering_distance_cols of "euclidean", and clustering_method = "complete" (any method hclust accepts). Set display_numbers = TRUE to print values in the cells (default FALSE), and pass a data frame to annotation_col to add column annotations matched by row names.

Step 3. ggplot2: geom_tile()

  1. Reshape the matrix to long format: df <- as.data.frame(as.table(as.matrix(mtcars))). This gives columns Var1, Var2 and Freq.
  2. Plot: ggplot(df, aes(Var2, Var1)) + geom_tile(aes(fill = Freq)).

geom_tile() uses the centre of each tile and its size. geom_raster() is documented as a high-performance special case for when all tiles are the same size. Because geom_tile() does no clustering, order the rows and columns yourself if you need clusters.

How to make a correlation heatmap in R

A correlation heatmap colours the output of cor(). The signature is cor(x, y = NULL, use = "everything", method = c("pearson", "kendall", "spearman")).

  1. Compute the matrix: r <- cor(mtcars). Add method = "spearman" for rank correlation.
  2. Base R: heatmap(r, symm = TRUE). For a square symmetric matrix, symm = TRUE is the documented setting, and it also makes the default scaling "none".
  3. pheatmap: pheatmap(r, display_numbers = TRUE). The default scale = "none" already leaves correlations unscaled.
  4. ggplot2: rdf <- as.data.frame(as.table(r)) then ggplot(rdf, aes(Var1, Var2, fill = Freq)) + geom_tile().

Do not row-scale a correlation matrix. With the base default (scale = "row" when symm is false) the colours no longer show the correlation coefficients themselves, which is an easy silent mistake.

Output and how to read it

  • Colour encodes the value after any scaling. With scale = "row" or "column" it shows position relative to that row or column, not the raw number.
  • Dendrograms show the hierarchical clustering. Rows or columns that join low in the tree are more similar under the chosen distance and linkage (dist and hclust defaults in base R; euclidean and complete in pheatmap).
  • Row and column order follows the clustering unless you switched it off, so two heatmaps of the same data can look different if the clustering settings differ.

In a Methods section, report the correlation method, the use setting, any scaling, and the distance and linkage used for clustering. Those four choices are what a reader needs to reproduce the figure.

Troubleshooting

The correlation heatmap has blank cells or NA

The default is use = "everything", so a correlation is NA whenever a contributing observation is NA. Other documented options are "all.obs" (an error if any NA), "complete.obs", "na.or.complete" and "pairwise.complete.obs". Note that the pairwise option can return a matrix that is not positive semi-definite and may still contain NA.

The colours do not match the numbers

Check scale. Base heatmap() defaults to "row" for non-symmetric input; pheatmap defaults to "none".

The rows moved

Clustering reorders them. In base R set Rowv = NA; in pheatmap set cluster_rows = FALSE.

The ggplot2 tiles have gaps or uneven sizes

With geom_tile() each tile has its own centre and size. Use geom_raster() only when all tiles are the same size.

Alternatives in R (comparison table)

Approach Package Clusters by default Default scaling
heatmap() stats (base R) Yes, with dendrograms (dist, hclust) "row" unless symm = TRUE
pheatmap() pheatmap Yes (euclidean, complete) "none"
geom_tile() / geom_raster() ggplot2 No; you order the data None; you transform the data

For other common figure types in R, see histograms in R, scatterplots in R and box plots in R.

FAQ

How do I make a heatmap in R?

Convert your data to a numeric matrix and call heatmap(x) from base R, or pheatmap(x) after loading the pheatmap package. For a ggplot2 version, reshape to long format and use geom_tile(aes(fill = value)).

How do I make a correlation heatmap in R?

Compute r <- cor(data), then pass it to heatmap(r, symm = TRUE) or pheatmap(r). Decide the use argument first if your data has missing values.

Should I scale the data before plotting?

Scale when variables are on different units and you want to compare patterns, not raw size. Do not scale a correlation matrix.

Sources (official documentation, checked 2026-10-29)

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about Heatmap in R: heatmap(), pheatmap and ggplot2

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →

Ask CASRAI · Regulatory Radar

Research-admin question? Get an answer that links its sources.

An AI assistant specialized in research administration. Every answer links its sources to check before you act. 2 questions free, no account. $29/month after.

  • Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.
  • Every answer numbers its sources and links each one, so you can check the source yourself.