The aim of the package plot.matrix
is to visualize a
matrix as is with a heatmap. Automatic reordering of rows and columns is
only done if necessary. This is different as in similar function like
heatmap
. Additionally it should be user-friendly and give
access to a lot of options if necessary.
Currently the package implements the S3 functions below such that you
can use the generic plot
function to plot matrices as
heatmaps:
plot.matrix
for a heatmap for a plain matrix,plot.loadings
for a heatmap for a loadings matrix from
factor analysis or principal component analysis (reordering of
rows!).The plot itself is composed by a heatmap (usually left) where colors represent matrix entries and a key (usually right) which links the colors to the values.
plot.matrix
uses the command assignColors
,
also part of plot.matrix
, assigns to each value in
x
a color based on the parameters breaks
,
col
and na.col
given.
In case of a numeric matrix breaks
can be
x
,In case of a non-numeric vector breaks
must contain all
values which are will get a color. If breaks
is not given
then a sensible default is chosen: in case of a numeric vector derived
from pretty
and otherwise all unique values/levels are
used.
col
can be either be a vector of colors or a function
which generates via col(n)
a set of n
colors.
The default is to use heat.colors
.
In case that you want to provide your own color palettes/functions for plotting there are several good choices within R packages:
Source: Datanovia - Top R Color Palettes to Know for Great Data Visualization
The plot is created in several steps
plot
command to create the basic
plotpolygon
commandtext
command in a polygonaxis
command
into the plotaxis
and the
polygon
commandplot.matrix( | x, | ||
y | = | NULL, | |
breaks | = | NULL, | |
col | = | heat.colors, | |
na.col | = | “white”, | |
na.cell | = | TRUE, | |
na.print | = | TRUE, | |
digits | = | NA, | |
fmt.cell | = | NULL, | |
fmt.key | = | NULL, | |
spacing.key | = | c(1, 0.5, 0), | |
polygon.cell | = | NULL, | |
polygon.key | = | NULL, | |
text.cell | = | NULL, | |
key | = | list(side = 4, las = 1), | |
axis.col | = | list(side = 1), | |
axis.row | = | list(side = 2), | |
axis.key | = | NULL, | |
max.col | = | 70, | |
…) |
You may influence the appearance by setting your own parameters:
...
all parameters given here will be given to the
plot
command, e.g. xlab
, ylab
,
….polygon.cell
list of parameters for drawing polygons
for matrix entriestext.cell
list of parameters for putting for matrix
entries as textsaxis.col
and axis.row
list of parameters
for drawing for row and column axeskey
, axis.key
, spacing.key
and polygon.key
to draw the keymax.col
to determine when text color and background
color to nearYou may set global parameters for all subsequent calls of
axis
, polygon
and text
via the
...
. The following parameters are supported
function | parameter(s) |
---|---|
axis |
cex.axis , col.axis ,
col.ticks , font , font.axis ,
hadj , las , lwd.ticks ,
line , outer , padj ,
tck , tcl , tick |
polygon |
angle , border , density |
text |
cex , font , vfont |
Use the parameter border=NA
.
Use the parameter asp=TRUE
.
Use the parameter las
, the style of axis labels, in
axis.col
and/or axis.row
with
0
= always parallel to the axis [default],1
= always horizontal,2
= always perpendicular to the axis, and3
= always vertical.You need to access the position of the cell text used by accessing
the invisible return of plot.matrix
. The
cell.text
contains the parameters used to draw the
text.
Note the double braces: [[i,j]]
param_est <- matrix(runif(25), nrow=5)
par(mar=c(5.1, 4.1, 4.1, 4.1)) # adapt margins such that all labels are visible
res <- plot(param_est, digits=2, text.cell=list(pos=3, cex=0.75))
sderr_est <- matrix(runif(25)/10, nrow=5)
for (i in 1:nrow(param_est)) {
for (j in 1:ncol(param_est)) {
args <- res$cell.text[[i,j]]
args$labels <- paste0('(', fmt(sderr_est[i,j], 3), ')')
args$cex <- 0.5
args$pos <- 1
do.call(text, args)
}
}
Or alternatively
param_est <- matrix(runif(25), nrow=5)
par(mar=c(5.1, 4.1, 4.1, 4.1)) # adapt margins such that all labels are visible
res <- plot(param_est, digits=2, text.cell=list(cex=0.75))
sderr_est <- matrix(runif(25)/10, nrow=5)
for (i in 1:nrow(param_est)) {
for (j in 1:ncol(param_est)) {
args <- res$cell.text[[i,j]]
args$labels <- paste0('(', round(sderr_est[i,j], 3), ')')
args$cex <- 0.6
args$y <- args$y-0.3
do.call(text, args)
}
}
plot.matrix
and the default scatter plot
in parallel?The example illustrates the problem: the loadings of the factor analysis should be plotted as matrix and the factor scores as a scatter plot.
par(mar=c(5.1, 4.1, 4.1, 4.1)) # adapt margins such that all labels are visible
library("plot.matrix")
library("psych")
fa <- fa(iris[,-5], 2)
#> Loading required namespace: GPArotation
plot(fa$loadings)
data.frame
plot.default
plot.matrix
permanentlyIf do not want to use the package plot.matrix
for
further plotting then unload the package including the installed S3
functions with devtools::unload
The default plot always draws a heatmap and a key where the colors
and breaks are determined by the entries of x
. In case of a
numeric matrix ten colors from heat.colors
are chosen and
eleven breaks with cover the range of entries with an equidistant grid.
In case of a non-numeric matrix each unique element gets a color
determined from heat.colors
.
In case of a numeric matrix the breaks
give the interval
borders for a color otherwise for each unique matrix entry
breaks
should contain a value. If breaks
are
not given then they will be determined from the matrix object by using
the pretty
function of base R.
The col
parameter is either a vector of colors used or a
function mycolor(n)
which returns n
colors on
request.
Note that for numeric matrices must hold
length(breaks)==length(col)+1
and for non-numeric matrices
length(breaks)==length(col)
.
The parameter na.col
determines the color for missing
values and for matrix entries outside the current color scheme.
For deleting the key set key=NULL
:
For moving the key to a different axis use key
or
axis.key
. Note that only a warning is issued if the axes
for rows, columns or the key are at the same side.
par(mar=c(5.1, 4.1, 5.1, 4.1)) # adapt margins
# move key to the top and make axis text smaller
plot(x, key=list(side=3, cex.axis=0.75), breaks=c(0,1))
The parameter spacing.key
gives the spacing between plot
and the key, the width of the key and the spacing between the key and
the axis. If you give a vector of length 1 or 2 then the missing values
will be appended with the defaults c(1, 0.5, 0)
par(mar=c(5.1, 4.1, 5.1, 4.1)) # adapt margins
# move key to the top, make axis text smaller, and move key farther away from the plot
plot(x, key=list(side=3, cex.axis=0.75), breaks=c(0,1), spacing.key=2)
For a very large matrix
You can either use digits
which changes the output
format for all text. If you just want to change the output format for
the key labels use fmt.key
, e.g.
par(mar=c(5.1, 4.1, 4.1, 4.1)) # adapt margins
# no plus sign
plot(x, fmt.key="%.3f", breaks=c(0,1))
For details to the format string see sprintf
, for
non-numeric matrices %s
should be used.
Warning: The format string is passed down the OS’s sprintf function, and incorrect formats can cause the latter to crash the R process. R does perform sanity checks on the format, but not all possible user errors on all platforms have been tested, and some might be terminal.
As default the row axis is drawn as y-axis and the col axis is drawn
as x-axis with row and column indices. If the matrix has
rownames(x)
or colnames(x)
then they will
used. The same holds for the labels of the axes if
names(dimnames(x))
is not empty.
For moving, e.g. the column axis to the top, use
par(mar=c(5.1, 4.1, 5.1, 4.1)) # adapt margins
plot(x, axis.col=list(side=3, cex.axis=0.7), axis.row=list(cex.axis=0.7))
# or alternatively set cex.axis for all axes and use abbreviated positioning
plot(x, axis.col=3, cex.axis=0.7)
For not drawing any axes use
You can either use digits
which changes the output
format for all text. If you just want to change the output format for
the key labels use fmt.cell
, e.g.
NA
handlingUsually NA
values in a matrix are drawn as white boxes
which determined by the value of the na.col
parameter
(default: white) and if the matrix entries shown by `NA
x <- matrix(c(NA, 1, 2, 3), ncol=2)
par(mar=c(5.1, 4.1, 4.1, 4.1)) # adapt margins
plot(x, na.col='black', fmt.cell='%.0f')
You may enforce with na.print
no printing of
NA
s or using a replacement text
x <- matrix(c(NA, 1, 2, 3), ncol=2)
par(mar=c(5.1, 4.1, 4.1, 4.1)) # adapt margins
plot(x, na.col='black', fmt.cell='%.0f', na.print=FALSE)
With na.cell
you suppress printing of matrix entries at
all
It may happen that the text color and cell background color are too near which means you can not read the text anymore in a cell
par(mar=c(5.1, 4.1, 4.1, 4.1)) # adapt margins
# Never replace text color by black or white
plot(x, digits=2, text.cell=list(col="yellow", cex=0.75), max.col=-1)
By default the text color is replaced by black or white (which is further away)
par(mar=c(5.1, 4.1, 4.1, 4.1)) # adapt margins
plot(x, digits=2, text.cell=list(col="yellow", cex=0.75))
Just replace text color if colors are nearer then the default
max.col=70
par(mar=c(5.1, 4.1, 4.1, 4.1)) # adapt margins
# In fewer cells the text color will be replaced by black
plot(x, digits=2, text.cell=list(col="yellow", cex=0.75), max.col=35)
or farer away then the default
par(mar=c(5.1, 4.1, 4.1, 4.1)) # adapt margins
# In more cells the text color will be replaced by black
plot(x, digits=2, text.cell=list(col="yellow", cex=0.75), max.col=140)
Of course, the best solution is to choose a good color scheme and a good text color ;)
The plot
command returns invisibly a list of the
elements drawn, a bit like hist
. A NULL
entry
means the element has not been drawn. The data may be useful for adding
own elements in the graphic.
# numeric matrix
x <- matrix(runif(35), ncol=5) # create a numeric matrix object
par(mar=c(5.1, 4.1, 4.1, 4.1)) # adapt margins
res <- plot(x)
Available are the parameters for
cell.polygon
, cell.text
: the polygon and
the text used to draw a matrix element,key.polygon
, key.axis
: the polygon and the
axis used to draw a key element, andplot
, axis.col
, axis.row
: the
basic plot and the axes drawn.#####
names(res)
#> [1] "plot" "cell.polygon" "cell.text" "axis.col" "axis.row"
#> [6] "key.axis" "key.polygon"
# parameters of polygon which was used to draw x[3,4]
res$cell.polygon[[3,4]]
#> $y
#> [1] 4.5 5.5 5.5 4.5
#>
#> $x
#> [1] 3.5 3.5 4.5 4.5
#>
#> $col
#> [1] "#FF5500"
#####
# parameters of text which was used for x[3,4]
res$cell.text[[3,4]] # NULL since no text was drawn
#> NULL
#####
# parameters of polygon which was used to draw the second key element
res$key.polygon[[2]]
#> $x
#> [1] 6.0 6.0 6.5 6.5
#>
#> $y
#> [1] 2.2 3.4 3.4 2.2
#>
#> $col
#> [1] "#FF5500"
x <- matrix(runif(35), ncol=5) # create a numeric matrix object
par(mar=c(5.1, 4.1, 4.1, 4.1)) # adapt margins
res <- plot(x)
for (i in 1:length(res$cell.polygon)) {
args <- res$cell.polygon[[i]]
args$col <- NA # use no color
args$density <- 20*x[i] # density depends on matrix entries
args$angle <- 45
do.call("polygon", args)
}
Please note that the PNGs have a transparent background. It depends on the graphic device how the transparency is taken into account.
x <- matrix(runif(35), ncol=5) # create a numeric matrix object
par(mar=c(5.1, 4.1, 4.1, 4.1)) # adapt margins
res <- plot(x)
#
library("png")
# PNGs are created from wikimedia commons images, CC0 by C. Koltzenburg
# https://commons.wikimedia.org/wiki/File:C.Koltzenburg_-_smiley-yes.xcf
# https://commons.wikimedia.org/wiki/File:C.Koltzenburg_-_smiley_no.xcf
happy <- readPNG(system.file('png', 'happy.png', package="plot.matrix"))
sad <- readPNG(system.file('png', 'sad.png', package="plot.matrix"))
for (i in 1:length(res$cell.polygon)) {
args <- res$cell.polygon[[i]]
if (x[i]>0.5) {
rasterImage(happy, args$x[1]+0.1, args$y[1]+0.1, args$x[3]-0.1, args$y[2]-0.1)
} else {
rasterImage(sad, args$x[1]+0.1, args$y[1]+0.1, args$x[3]-0.1, args$y[2]-0.1)
}
}
For some special matrices we have special plot routines:
plot.loadings
plot.cor
plot.assoc
plot.pvalue
All plot routines support the parameters
gray
and grey
for gray scale imagereorder
for reordering rows (default:
reorder=TRUE
)Note that matrix columns are only reordered if the column names are identical to the row names.
In factor or principal component analysis you may want to view the
loadings matrix. The S3 function plot.loadings
allows to
create a heatmap with loadings. It differs from plotting a matrix by
c(-sqrt(c(1, 0.75, 0.5, 0.25, 0.16)), 0, sqrt(c(1, 0.75, 0.5, 0.25, 0.16)))
,A typical threshold in factor analysis is an absolute loading greater equal 0.5; thus a factor “explains” 25% of the variance of a variable. Further thresholds are selected such that they explain 50% and 75% of the variable variance. Sometimes it might be useful to check whether there are loadings a little bit under 0.5, therefore another threshold of 0.4 is added.
All parameters described in Modifying a plot can be
used in plot.loadings
as well.
library('plot.matrix')
library('psych')
data(bfi.2)
fa <- fa(bfi.2, 5, rotate="varimax")
par(mar=c(5.1, 4.1, 4.1, 4.1)) # adapt margins
plot(loadings(fa), cex=0.5)
For using a gray color scheme add gray=TRUE
or
grey=TRUE
to the call
For not printing loading entries use the parameter
digits
:
The S3 function plot.cor
and plot.assoc
allow to create a heatmap with the coefficients. It differs from
plotting a matrix by
dist
and hclust
with the defaults on the
rows,All parameters described in Modifying a plot can be
used in plot.assoc
or plot.cor
as well.
library('plot.matrix')
data(Titanic.cramer)
par(mar=c(5.1, 4.1, 4.1, 4.1)) # adapt margins
plot(as.assoc(Titanic.cramer))
library('plot.matrix')
library('datasets')
c <- cor(airquality[,1:4], use="complete")
par(mar=c(5.1, 4.1, 4.1, 4.1)) # adapt margins
plot(as.cor(c))
For using a gray color scheme add gray=TRUE
or
grey=TRUE
to the call
For not printing loading entries use the parameter
digits
:
The S3 function plot.pvalue
allows to create a heatmap
from a matrix of p values. It differs from plotting a matrix by
dist
and hclust
with the defaults on the
rows,All parameters described in Modifying a plot can be
used in plot.pvalue
as well.
library('plot.matrix')
data(air.pvalue)
par(mar=c(5.1, 4.1, 4.1, 4.1)) # adapt margins
plot(as.pvalue(air.pvalue))
For using a gray color scheme add gray=TRUE
or
grey=TRUE
to the call
For not printing loading entries use the parameter
digits
: