pairs(): Specifying axes limits of the subpanels - r

Consider the following example:
data(iris)
pairs(iris[1:4],xlim=c(0,8), ylim = c(0,8))
As you can see, the axes limits for all subpanels have been altered.
However, the alteration required is the specification of xlim and ylim for each subpanel row/column individually.
I perused SO and could not find a suitable answer.

You cannot do this directly. But if you are willing to go to the source code of pairs, it can easily be done. Below you will find my version. Note that this is mostly just the original with a few lines of code changed.
my.pairs <- function (x, labels, panel = points, ..., lower.panel = panel,
upper.panel = panel, diag.panel = NULL, text.panel = textPanel,
label.pos = 0.5 + has.diag/3, line.main = 3, cex.labels = NULL,
font.labels = 1, row1attop = TRUE, gap = 1, log = "", xlim=NULL, ylim=NULL)
{
if (doText <- missing(text.panel) || is.function(text.panel))
textPanel <- function(x = 0.5, y = 0.5, txt, cex, font) text(x,
y, txt, cex = cex, font = font)
localAxis <- function(side, x, y, xpd, bg, col = NULL, main,
oma, ...) {
xpd <- NA
if (side%%2L == 1L && xl[j])
xpd <- FALSE
if (side%%2L == 0L && yl[i])
xpd <- FALSE
if (side%%2L == 1L)
Axis(x, side = side, xpd = xpd, ...)
else Axis(y, side = side, xpd = xpd, ...)
}
localPlot <- function(..., main, oma, font.main, cex.main) plot(...)
localLowerPanel <- function(..., main, oma, font.main, cex.main) lower.panel(...)
localUpperPanel <- function(..., main, oma, font.main, cex.main) upper.panel(...)
localDiagPanel <- function(..., main, oma, font.main, cex.main) diag.panel(...)
dots <- list(...)
nmdots <- names(dots)
if (!is.matrix(x)) {
x <- as.data.frame(x)
for (i in seq_along(names(x))) {
if (is.factor(x[[i]]) || is.logical(x[[i]]))
x[[i]] <- as.numeric(x[[i]])
if (!is.numeric(unclass(x[[i]])))
stop("non-numeric argument to 'pairs'")
}
}
else if (!is.numeric(x))
stop("non-numeric argument to 'pairs'")
panel <- match.fun(panel)
if ((has.lower <- !is.null(lower.panel)) && !missing(lower.panel))
lower.panel <- match.fun(lower.panel)
if ((has.upper <- !is.null(upper.panel)) && !missing(upper.panel))
upper.panel <- match.fun(upper.panel)
if ((has.diag <- !is.null(diag.panel)) && !missing(diag.panel))
diag.panel <- match.fun(diag.panel)
if (row1attop) {
tmp <- lower.panel
lower.panel <- upper.panel
upper.panel <- tmp
tmp <- has.lower
has.lower <- has.upper
has.upper <- tmp
}
nc <- ncol(x)
if (nc < 2)
stop("only one column in the argument to 'pairs'")
if (doText) {
if (missing(labels)) {
labels <- colnames(x)
if (is.null(labels))
labels <- paste("var", 1L:nc)
}
else if (is.null(labels))
doText <- FALSE
}
oma <- if ("oma" %in% nmdots)
dots$oma
main <- if ("main" %in% nmdots)
dots$main
if (is.null(oma))
oma <- c(4, 4, if (!is.null(main)) 6 else 4, 4)
opar <- par(mfrow = c(nc, nc), mar = rep.int(gap/2, 4), oma = oma)
on.exit(par(opar))
dev.hold()
on.exit(dev.flush(), add = TRUE)
xl <- yl <- logical(nc)
if (is.numeric(log))
xl[log] <- yl[log] <- TRUE
else {
xl[] <- grepl("x", log)
yl[] <- grepl("y", log)
}
for (i in if (row1attop)
1L:nc
else nc:1L) for (j in 1L:nc) {
l <- paste0(ifelse(xl[j], "x", ""), ifelse(yl[i], "y",
""))
if (is.null(xlim) & is.null(ylim))
localPlot(x[, j], x[, i], xlab = "", ylab = "", axes = FALSE,
type = "n", ..., log = l)
if (is.null(xlim) & !is.null(ylim))
localPlot(x[, j], x[, i], xlab = "", ylab = "", axes = FALSE,
type = "n", ..., log = l, ylim=ylim[j,i,])
if (!is.null(xlim) & is.null(ylim))
localPlot(x[, j], x[, i], xlab = "", ylab = "", axes = FALSE,
type = "n", ..., log = l, xlim = xlim[j,i,])
if (!is.null(xlim) & !is.null(ylim))
localPlot(x[, j], x[, i], xlab = "", ylab = "", axes = FALSE,
type = "n", ..., log = l, xlim = xlim[j,i,], ylim=ylim[j,i,])
if (i == j || (i < j && has.lower) || (i > j && has.upper)) {
box()
if (i == 1 && (!(j%%2L) || !has.upper || !has.lower))
localAxis(1L + 2L * row1attop, x[, j], x[, i],
...)
if (i == nc && (j%%2L || !has.upper || !has.lower))
localAxis(3L - 2L * row1attop, x[, j], x[, i],
...)
if (j == 1 && (!(i%%2L) || !has.upper || !has.lower))
localAxis(2L, x[, j], x[, i], ...)
if (j == nc && (i%%2L || !has.upper || !has.lower))
localAxis(4L, x[, j], x[, i], ...)
mfg <- par("mfg")
if (i == j) {
if (has.diag)
localDiagPanel(as.vector(x[, i]), ...)
if (doText) {
par(usr = c(0, 1, 0, 1))
if (is.null(cex.labels)) {
l.wid <- strwidth(labels, "user")
cex.labels <- max(0.8, min(2, 0.9/max(l.wid)))
}
xlp <- if (xl[i])
10^0.5
else 0.5
ylp <- if (yl[j])
10^label.pos
else label.pos
text.panel(xlp, ylp, labels[i], cex = cex.labels,
font = font.labels)
}
}
else if (i < j)
localLowerPanel(as.vector(x[, j]), as.vector(x[,
i]), ...)
else localUpperPanel(as.vector(x[, j]), as.vector(x[,
i]), ...)
if (any(par("mfg") != mfg))
stop("the 'panel' function made a new plot")
}
else par(new = FALSE)
}
if (!is.null(main)) {
font.main <- if ("font.main" %in% nmdots)
dots$font.main
else par("font.main")
cex.main <- if ("cex.main" %in% nmdots)
dots$cex.main
else par("cex.main")
mtext(main, 3, line.main, outer = TRUE, at = 0.5, cex = cex.main,
font = font.main)
}
invisible(NULL)
}
With this changed pairsfunction, you can now do the following:
data(iris)
pairs(iris[1:4],xlim=c(0,8), ylim = c(0,8))
# xpecifying limits (now as arrays...)
# dims 1-2: panel
# dim 3: lower und upper limit
my.xlim <- array(0, dim=c(4,4,2))
my.xlim[,,2] <- 8
my.ylim <- my.xlim
my.xlim[1,,1] <- 4
my.pairs(iris[1:4], xlim=my.xlim)
# careful: the following would work, but does not adjust the labels!
my.xlim[2,3,2] <- 6
my.pairs(iris[1:4], xlim=my.xlim)

Related

EnQuireR package for questionnaire analysis

I am trying to explore EnQuireR package for questionnaire analysis (for tea data). But ENbarplot & XvsYbarplot gives error:
ENbarplot(tea, 20, numr=1, numc=1, spl=TRUE)
Error in hsv(h = a * m, s = 0.4 + (cont[j]/max) * 0.6, v = 1, 1, 1) :
unused argument (1)
&
XvsYbarplot("socio.professional.category","sex",tea, legend.text=TRUE)
Error in hsv(h = a * i, s = 1, v = 1, 1, 1) : unused argument (1)
Also, I am facing problems in interpreting the output of chisq.desc() function. Does colored cells represent significant association between corresponding variables? Can anyone please explain in detail?
The issue was with the hsv function in the graphic devices utilities. There is an extra argument passed the function making it to fail. I tried fixing it. The code below should work if you're still interested in using the package
barplot_function1 <- function (dataset, X, spl = FALSE, numr = NULL, numc = NULL,
cex = 1, colour = NULL)
{
mult = length(X)
col = rep(0)
count_mod <- rep(0)
a <- 1/mult
for (m in 1:mult) {
if (spl) {
cont <- sort(table(dataset[, X[m]]))
}
else {
cont <- table(dataset[, X[m]])
}
NR <- dim(cont)
count_mod <- c(count_mod, NR)
max <- max(cont)
coli <- rep(0, NR)
for (j in 1:NR) {
if (cont[j] == max) {
coli[j] <- hsv(h = a * m, s = 1, v = 1, 1)
}
else {
coli[j] <- hsv(h = a * m, s = 0.4 + (cont[j]/max) *
0.6, v = 1, 1)
}
}
col <- c(col, coli)
}
col <- col[-1]
count_mod <- count_mod[-1]
summ <- cumsum(count_mod)
na = matrix(0, 1, mult)
if (is.null(numr)) {
if (is.null(numc)) {
numr = numc = 2
}
}
par(mfrow = c(numr, numc), yaxt = "n")
tpolice <- par("cex")
par(xpd = T, mar = par()$mar + c(0, 1, 0, 0))
for (m in 1:mult) {
for (i in 1:((dim(dataset)[2])/(numr * numc))) {
if (m == ((numr * numc) * i) + 1) {
x11()
par(mfrow = c(numr, numc), yaxt = "n")
}
}
k = 0
for (i in 1:length(dataset[, X[m]])) {
if ((is.na(dataset[, X[m]])[[i]]) == TRUE) {
k = k + 1
}
}
na[m] = k/length(dataset[, X[m]])
if (spl == TRUE) {
coord = barplot(sort(table(dataset[, X[m]])), beside = TRUE,
las = 2, horiz = TRUE, main = names(dataset)[X[m]],
col = col[(summ[m] - count_mod[m] + 1:summ[m])])
text(x = 2, y = coord, labels = names(sort(table(dataset[,
X[m]]))), adj = 0, cex = cex, col = colour)
}
if (spl == FALSE) {
coord = barplot(table(dataset[, X[m]]), beside = TRUE,
las = 2, horiz = TRUE, main = names(dataset)[X[m]],
col = col[(summ[m] - count_mod[m] + 1:summ[m])])
text(x = 2, y = coord, labels = levels(dataset[,
X[m]]), adj = 0, cex = cex, col = colour)
}
mtext(paste(c("Percentage of missing values =", round(na[m],
2) * 100, "%"), collapse = " "), side = 3, line = -0.1,
cex = tpolice, adj = 0)
}
}
ENbarplotfixed <- function (dataset, X, spl = FALSE, numr = NULL, numc = NULL,
report = FALSE)
{
if (report == FALSE) {
barplot_function1(dataset, X, spl, numr, numc)
}
if `enter code here`(report == TRUE) {
assign("X", X, envir = .GlobalEnv)
assign("dataset", dataset, envir = .GlobalEnv)
a = getwd()
dir.create(paste(a, "/EnQuireR/", sep = ""))
file.copy(paste(.libPaths()[1], "/EnQuireR/Sweave/sty/fancyvrb.sty",
sep = ""), paste(a, "/EnQuireR/fancyvrb.sty", sep = ""))
file.copy(paste(.libPaths()[1], "/EnQuireR/Sweave/sty/Sweave.sty",
sep = ""), paste(a, "/EnQuireR/Sweave.sty", sep = ""))
file.copy(paste(.libPaths()[1], "/EnQuireR/Sweave/sty/upquote.sty",
sep = ""), paste(a, "/EnQuireR/upquote.sty", sep = ""))
file.copy(paste(.libPaths()[1], "/EnQuireR/Sweave/sty/algorithmic.sty",
sep = ""), paste(a, "/EnQuireR/algorithmic.sty",
sep = ""))
setwd(paste(a, "/EnQuireR", sep = ""))
Sweave(paste(.libPaths()[1], "/EnQuireR/Sweave/barplot/Univariate_report.Rnw",
sep = ""), driver = RweaveLatex(), syntax = getOption("SweaveSyntax"))
tools::texi2dvi(paste(a, "/EnQuireR/Univariate_report.tex",
sep = ""), pdf = TRUE)
setwd(a)
}
}
#plot
ENbarplotfixed(tea,20,spl=T,numr=1,numc=1)
#plot upon condition
XvsYbarplotfixed <- XvsYbarplotfixed <- function (var1, var2, dataset, width = 1, space = NULL, names.arg = NULL,
legend.text = NULL, horiz = FALSE, density = NULL, angle = 45,
col = NULL, border = par("fg"), main = NULL, sub = NULL,
xlab = NULL, ylab = NULL, xlim = NULL, ylim = NULL, xpd = TRUE,
log = "", axes = TRUE, axisnames = TRUE, cex.axis = par("cex.axis"),
cex.names = par("cex.axis"), inside = TRUE, plot = TRUE,
axis.lty = 0, offset = 0, add = FALSE, ...)
{
dataset <- as.data.frame(dataset)
if (is.character(var1) & is.character(var2)) {
num_var1 <- match(var1, names(dataset))
num_var2 <- match(var2, names(dataset))
height <- table(dataset[, num_var1], dataset[, num_var2])
}
else {
height <- table(var1, var2)
}
if (!missing(inside))
.NotYetUsed("inside", error = FALSE)
if (is.null(space))
space <- if (is.matrix(height))
c(0, 1)
else 0.2
space <- space * mean(width)
if (plot && axisnames && is.null(names.arg))
names.arg <- if (is.matrix(height))
colnames(height)
else names(height)
if (is.vector(height) || (is.array(height) && (length(dim(height)) ==
1))) {
height <- cbind(height)
if (is.null(col))
if (is.null(col))
col <- rep(0)
NR <- length(height)
max <- max(height)
for (i in 1:NR) {
if (height[i] == max) {
coli <- hsv(h = 1, s = 1, v = 1, 1)
col <- cbind(col, coli)
}
else {
coli <- hsv(h = 1, s = 0.4 + (height[i]/max) *
0.6, v = 1, 1)
col <- c(col, coli)
}
}
col <- col[-1]
}
else if (is.matrix(height)) {
if (is.null(col))
NR <- nrow(height)
NC <- ncol(height)
col = rep(0)
a <- 1/NC
for (i in 1:NC) {
max <- max(height[, i])
coli <- rep(0, NR)
for (j in 1:NR) {
if (height[j, i] == max) {
coli[j] <- hsv(h = a * i, s = 1, v = 1, 1)
}
else {
coli[j] <- hsv(h = a * i, s = 0.4 + (height[j,
i]/max) * 0.6, v = 1, 1)
}
}
col <- c(col, coli)
}
col <- col[-1]
}
else stop("'height' must be a vector or a matrix")
if (is.logical(legend.text))
legend.text <- if (legend.text && is.matrix(height))
rownames(height)
stopifnot(is.character(log))
logx <- logy <- FALSE
if (log != "") {
logx <- length(grep("x", log)) > 0L
logy <- length(grep("y", log)) > 0L
}
if ((logx || logy) && !is.null(density))
stop("Cannot use shading lines in bars when log scale is used")
NR <- nrow(height)
NC <- ncol(height)
if (length(space) == 2)
space <- rep.int(c(space[2], rep.int(space[1], NR - 1)),
NC)
width <- rep(width, length.out = NR)
offset <- rep(as.vector(offset), length.out = length(width))
delta <- width/2
w.r <- cumsum(space + width)
w.m <- w.r - delta
w.l <- w.m - delta
log.dat <- (logx && horiz) || (logy && !horiz)
if (log.dat) {
if (min(height + offset, na.rm = TRUE) <= 0)
stop("log scale error: at least one 'height + offset' value <= 0")
if (logx && !is.null(xlim) && min(xlim) <= 0)
stop("log scale error: 'xlim' <= 0")
if (logy && !is.null(ylim) && min(ylim) <= 0)
stop("log scale error: 'ylim' <= 0")
rectbase <- if (logy && !horiz && !is.null(ylim))
ylim[1]
else if (logx && horiz && !is.null(xlim))
xlim[1]
else 0.9 * min(height, na.rm = TRUE)
}
else rectbase <- 0
rAdj <- offset + (if (log.dat)
0.9 * height
else -0.01 * height)
delta <- width/2
w.r <- cumsum(space + width)
w.m <- w.r - delta
w.l <- w.m - delta
num_mod <- nlevels(var1)
if (horiz) {
if (is.null(xlim))
xlim <- range(rAdj, height + offset, na.rm = TRUE)
if (is.null(ylim))
ylim <- c(min(w.l), max(w.r) + num_mod + (num_mod -
1))
}
else {
if (is.null(xlim))
xlim <- c(min(w.l), max(w.r))
if (is.null(ylim))
ylim <- range(rAdj, height + offset + num_mod * 5,
na.rm = TRUE)
}
w.m <- matrix(w.m, ncol = NC)
par(mar = par("mar") + c(1, 0, 0, 0))
if (plot) {
opar <- if (horiz)
par(xaxs = "i", xpd = xpd)
else par(yaxs = "i", xpd = xpd)
on.exit(par(opar))
if (!add) {
plot.new()
if (horiz) {
if (is.character(attributes(var1)$levels) ==
TRUE) {
if (max(nchar(attributes(var1)$levels)) > 8) {
par(mar = par("mar") + c(0, round(max(nchar(attributes(var1)$levels))/3),
0, 0))
}
}
else {
par(mar = par("mar") + c(0, 5, 0, 0))
}
plot.window(xlim, ylim, log = log, ...)
}
else plot.window(xlim, ylim, log = log, ...)
}
xyrect <- function(x1, y1, x2, y2, horizontal = TRUE,
...) {
if (horizontal)
rect(x1, y1, x2, y2, ...)
else rect(y1, x1, y2, x2, ...)
}
xyrect(rectbase + offset, w.l, c(height) + offset, w.r,
horizontal = horiz, angle = angle, density = density,
col = col, border = border)
if (axisnames && !is.null(names.arg)) {
at.l <- if (length(names.arg) != length(w.m)) {
if (length(names.arg) == NC)
colMeans(w.m)
else stop("incorrect number of names")
}
else w.m
if (!horiz)
if (is.character(attributes(var1)$levels) ==
TRUE) {
for (i in 1:nlevels(var2)) {
if (nchar(attributes(var2)$levels[i]) > 11)
names.arg[i] <- substring(attributes(var2)$levels[i],
1, 11)
}
}
if (horiz) {
axis(2, at = at.l, labels = names.arg, lty = axis.lty,
cex.axis = cex.names, las = 2)
}
else {
axis(1, at = at.l, labels = names.arg, lty = axis.lty,
cex.axis = cex.names, las = 0)
}
}
if (!is.null(legend.text)) {
legend.col <- rep(col, length.out = length(legend.text))
if (!horiz) {
legend.text <- legend.text
legend.col <- legend.col
density <- rev(density)
angle <- rev(angle)
}
num.legend <- c("1st", "2nd", "3rd")
for (i in 4:20) {
num.legendi <- c(paste(i, "th"))
num.legend <- c(num.legend, num.legendi)
}
num.legend <- num.legend[1:dim(height)[1]]
xy <- par("usr")
if (horiz) {
legend2(xy[2] - xinch(0.1), xy[4] - yinch(0.1),
legend = paste(num.legend, "bar:", legend.text),
angle = angle, density = density, fill = legend.col,
bty = "n", cex = 1 - 0.04 * num_mod, xjust = 1,
yjust = 1)
}
else {
legend2(xy[2] - xinch(0.1), xy[4] - yinch(0.1),
legend = paste(num.legend, "bar:", legend.text),
angle = angle, density = density, fill = legend.col,
bty = "n", xjust = 1, yjust = 1)
}
}
if (is.character(var1) & is.character(var2)) {
title(main = paste(names(dataset[num_var1]), "depending on",
names(dataset[num_var2])), sub = sub, xlab = xlab,
ylab = ylab, ...)
}
else {
for (i in 1:length(dataset)) {
a <- match(var1, dataset[, i])
b <- match(var2, dataset[, i])
if (any(is.na(a)) == FALSE) {
rep1 = i
}
if (any(is.na(b)) == FALSE) {
rep2 = i
}
}
title(main = paste(names(dataset[rep1]), "depending on",
names(dataset[rep2])), sub = sub, xlab = xlab,
ylab = ylab, ...)
}
if (axes)
if (horiz) {
axis(1, cex.axis = cex.axis, las = 0, ...)
}
else {
axis(2, cex.axis = cex.axis, las = 2, ...)
}
invisible(w.m)
}
else w.m
}

BTYD package. error in bgnbd plotting: need finite 'ylim' values for frequency in calibration

I'm having some trouble when plotting the "bgnbd.PlotFrequencyInCalibration" in the "BTYD" package.
There is no NA in the dataset and other plots works without error.
Below is my code for the plots:
CustData<- read.csv("~/ltv/CustData")
> cal.cbs<-cbind(CustData$t.x,CustData$x,CustData$T.cal,CustData$x.star)
> colnames(cal.cbs)<-c("t.x","x","T.cal","x.star")
est.params<-c(0.0313,0.9165,1.088,0.7903)
bgnbd.PlotFrequencyInCalibration(est.params,cal.cbs,7)
Error in plot.window(xlim, ylim, log = log, ...) :
need finite 'ylim' values
Any help would be appreciated. Thank you.
Kara
subset of the data
I fixed for pnbd.pnbd.PlotFrequencyInCalibration. Repeat the same for bgnbd. If you look at the actual function for pnbd.PlotFrequencyInCalibration :
"https://github.com/cran/BTYD/blob/master/R/pnbd.R" (check here)
pnbd.PlotFrequencyInCalibration <- function(params, cal.cbs, censor, plotZero = TRUE,
xlab = "Calibration period transactions", ylab = "Customers", title = "Frequency of Repeat Transactions") {
tryCatch(x <- cal.cbs[, "x"], error = function(e) stop("Error in pnbd.PlotFrequencyInCalibration: cal.cbs must have a frequency column labelled \"x\""))
tryCatch(T.cal <- cal.cbs[, "T.cal"], error = function(e) stop("Error in pnbd.PlotFrequencyInCalibration: cal.cbs must have a column for length of time observed labelled \"T.cal\""))
dc.check.model.params(c("r", "alpha", "s", "beta"), params, "pnbd.PlotFrequencyInCalibration")
if (censor > max(x))
stop("censor too big (> max freq) in PlotFrequencyInCalibration.")
n.x <- rep(0, max(x) + 1)
custs = nrow(cal.cbs)
for (ii in unique(x)) {
n.x[ii + 1] <- sum(ii == x)
}
n.x.censor <- sum(n.x[(censor + 1):length(n.x)])
n.x.actual <- c(n.x[1:censor], n.x.censor)
T.value.counts <- table(T.cal)
T.values <- as.numeric(names(T.value.counts))
n.T.values <- length(T.values)
total.probability <- 0
n.x.expected <- rep(0, length(n.x.actual))
for (ii in 1:(censor)) {
this.x.expected <- 0
for (T.idx in 1:n.T.values) {
T <- T.values[T.idx]
if (T == 0)
next
n.T <- T.value.counts[T.idx]
expected.given.x.and.T <- n.T * pnbd.pmf(params, T, ii - 1)
this.x.expected <- this.x.expected + expected.given.x.and.T
total.probability <- total.probability + expected.given.x.and.T/custs
}
n.x.expected[ii] <- this.x.expected
}
n.x.expected[censor + 1] <- custs * (1 - total.probability)
col.names <- paste(rep("freq", length(censor + 1)), (0:censor), sep = ".")
col.names[censor + 1] <- paste(col.names[censor + 1], "+", sep = "")
censored.freq.comparison <- rbind(n.x.actual, n.x.expected)
colnames(censored.freq.comparison) <- col.names
cfc.plot <- censored.freq.comparison
if (plotZero == FALSE)
cfc.plot <- cfc.plot[, -1]
n.ticks <- ncol(cfc.plot)
if (plotZero == TRUE) {
x.labels <- 0:(n.ticks - 1)
x.labels[n.ticks] <- paste(n.ticks - 1, "+", sep = "")
} else {
x.labels <- 1:(n.ticks)
x.labels[n.ticks] <- paste(n.ticks, "+", sep = "")
}
ylim <- c(0, ceiling(max(cfc.plot,na.rm = TRUE) * 1.1))
barplot(cfc.plot, names.arg = x.labels, beside = TRUE, ylim = ylim, main = title,
xlab = xlab, ylab = ylab, col = 1:2)
legend("topright", legend = c("Actual", "Model"), col = 1:2, lwd = 2)
return(censored.freq.comparison)
}
There is a line:
ylim <- c(0, ceiling(max(cfc.plot) * 1.1))
Add to it, na.rm=TRUE
ylim <- c(0, ceiling(max(cfc.plot,na.rm = TRUE) * 1.1))
Run the function again, should work now

Plotting error with Survplot and xlim in R

I'm plotting an incidence curve using the survplot package in R. I'm using the xlim option to limit the x-axis of my graph from 0-28. However, when I do this the x-axis will always extend to 30. The maximum potential value I have in my data is 28. Is there a way I can trim the x-axis to 28 instead of 30?
Here is my code and an example of the graph with the extra x-axis.
survplot(Survobj,
ylim=c(0,10),
xlim=c(0,28),
ylab = "Cumulative Incidence, %",
conf=c("bands"),
fun=function(x) {100*(1-x)},
n.risk=FALSE,
time.inc=1,
cex.n.risk=0.9)
I would attach an image, but I need 10 reputations points to do so (sorry!)
The code for survplot.rms (which has the same parameters as you are using and does exhibit the behavior you're describing) is base-R-grphics and it uses the pretty function to build the x-axis:
pretty(c(0,28))
#[1] 0 5 10 15 20 25 30
So if you want to change its behavior you will need to hack the code. It's not that hard to hack R code, but it's unclear to me whether you are ready for that adventure since you didn't even name the package from which you got the function correctly. It is a fairly long function. Experience has taught me that I need to provide newbies with a turnkey solution rather than just telling them to add a parameter and find the sections in the code to tweak. Here's how to add a 'notpretty' parameter that is used to determine whether just the max or the pretty function is used on the xlim argument:
survplot2 <- function (fit, ..., xlim, ylim = if (loglog) c(-5, 1.5) else if (what ==
"survival" & missing(fun)) c(0, 1), xlab, ylab, time.inc,
what = c("survival", "hazard"), type = c("tsiatis", "kaplan-meier"),
conf.type = c("log", "log-log", "plain", "none"), conf.int = FALSE,
conf = c("bands", "bars"), add = FALSE, label.curves = TRUE,
abbrev.label = FALSE, levels.only = FALSE, lty, lwd = par("lwd"),
col = 1, col.fill = gray(seq(0.95, 0.75, length = 5)), adj.subtitle = TRUE,
loglog = FALSE, fun, n.risk = FALSE, logt = FALSE, dots = FALSE,
dotsize = 0.003, grid = NULL, srt.n.risk = 0, sep.n.risk = 0.056,
adj.n.risk = 1, y.n.risk, cex.n.risk = 0.6, pr = FALSE,notpretty=FALSE)
{
what <- match.arg(what)
polyg <- ordGridFun(grid = FALSE)$polygon
ylim <- ylim
type <- match.arg(type)
conf.type <- match.arg(conf.type)
conf <- match.arg(conf)
opar <- par(c("mar", "xpd"))
on.exit(par(opar))
psmfit <- inherits(fit, "psm")
if (what == "hazard" && !psmfit)
stop("what=\"hazard\" may only be used for fits from psm")
if (what == "hazard" & conf.int > 0) {
warning("conf.int may only be used with what=\"survival\"")
conf.int <- FALSE
}
if (loglog) {
fun <- function(x) logb(-logb(ifelse(x == 0 | x == 1,
NA, x)))
use.fun <- TRUE
}
else if (!missing(fun)) {
use.fun <- TRUE
if (loglog)
stop("cannot specify loglog=T with fun")
}
else {
fun <- function(x) x
use.fun <- FALSE
}
if (what == "hazard" & loglog)
stop("may not specify loglog=T with what=\"hazard\"")
if (use.fun | logt | what == "hazard") {
dots <- FALSE
grid <- NULL
}
cox <- inherits(fit, "cph")
if (cox) {
if (n.risk | conf.int > 0)
surv.sum <- fit$surv.summary
exactci <- !(is.null(fit$x) | is.null(fit$y))
ltype <- "s"
}
else {
if (n.risk)
stop("the n.risk option applies only to fits from cph")
exactci <- TRUE
ltype <- "l"
}
par(xpd = NA)
ciupper <- function(surv, d) ifelse(surv == 0, 0, pmin(1,
surv * exp(d)))
cilower <- function(surv, d) ifelse(surv == 0, 0, surv *
exp(-d))
labelc <- is.list(label.curves) || label.curves
units <- fit$units
if (missing(ylab)) {
if (loglog)
ylab <- "log(-log Survival Probability)"
else if (use.fun)
ylab <- ""
else if (what == "hazard")
ylab <- "Hazard Function"
else ylab <- "Survival Probability"
}
if (missing(xlab)) {
if (logt)
xlab <- paste("log Survival Time in ", units, "s",
sep = "")
else xlab <- paste(units, "s", sep = "")
}
maxtime <- fit$maxtime
maxtime <- max(pretty(c(0, maxtime)))
if (missing(time.inc))
time.inc <- fit$time.inc
if (missing(xlim))
xlim <- if (logt)
logb(c(maxtime/100, maxtime))
else c(0, maxtime)
if (length(grid) && is.logical(grid))
grid <- if (grid)
gray(0.8)
else NULL
if (is.logical(conf.int)) {
if (conf.int)
conf.int <- 0.95
else conf.int <- 0
}
zcrit <- qnorm((1 + conf.int)/2)
xadj <- Predict(fit, type = "model.frame", np = 5, factors = rmsArgs(substitute(list(...))))
info <- attr(xadj, "info")
varying <- info$varying
if (length(varying) > 1)
stop("cannot vary more than one predictor")
adjust <- if (adj.subtitle)
info$adjust
else NULL
if (length(xadj)) {
nc <- nrow(xadj)
covpres <- TRUE
}
else {
nc <- 1
covpres <- FALSE
}
y <- if (length(varying))
xadj[[varying]]
else ""
curve.labels <- NULL
xd <- xlim[2] - xlim[1]
if (n.risk & !add) {
mar <- opar$mar
if (mar[4] < 4) {
mar[4] <- mar[4] + 2
par(mar = mar)
}
}
lty <- if (missing(lty))
seq(nc + 1)[-2]
else rep(lty, length = nc)
col <- rep(col, length = nc)
lwd <- rep(lwd, length = nc)
i <- 0
if (levels.only)
y <- gsub(".*=", "", y)
abbrevy <- if (abbrev.label)
abbreviate(y)
else y
abbrevy <- if (is.factor(abbrevy))
as.character(abbrevy)
else format(abbrevy)
if (labelc || conf == "bands")
curves <- vector("list", nc)
for (i in 1:nc) {
ci <- conf.int
ay <- if (length(varying))
xadj[[varying]]
else ""
if (covpres) {
adj <- xadj[i, , drop = FALSE]
w <- survest(fit, newdata = adj, fun = fun, what = what,
conf.int = ci, type = type, conf.type = conf.type)
}
else w <- survest(fit, fun = fun, what = what, conf.int = ci,
type = type, conf.type = conf.type)
time <- w$time
if (logt)
time <- logb(time)
s <- !is.na(time) & (time >= xlim[1])
surv <- w$surv
if (is.null(ylim))
ylim <- range(surv, na.rm = TRUE)
stratum <- w$strata
if (is.null(stratum))
stratum <- 1
if (!is.na(stratum)) {
cl <- if (is.factor(ay))
as.character(ay)
else format(ay)
curve.labels <- c(curve.labels, abbrevy[i])
if (i == 1 & !add) {
plot(time, surv, xlab = xlab, xlim = xlim, ylab = ylab,
ylim = ylim, type = "n", axes = FALSE)
mgp.axis(1, at = if (logt)
pretty(xlim)
# This is the line that was changed -----------------------
else seq(xlim[1], if(notpretty){max(xlim)}else{max(pretty(xlim))}, time.inc),
# end of modifications ------------------------
labels = TRUE)
mgp.axis(2, at = pretty(ylim))
if (!logt & (dots || length(grid))) {
xlm <- pretty(xlim)
xlm <- c(xlm[1], xlm[length(xlm)])
xp <- seq(xlm[1], xlm[2], by = time.inc)
yd <- ylim[2] - ylim[1]
if (yd <= 0.1)
yi <- 0.01
else if (yd <= 0.2)
yi <- 0.025
else if (yd <= 0.4)
yi <- 0.05
else yi <- 0.1
yp <- seq(ylim[2], ylim[1] + if (n.risk &&
missing(y.n.risk))
yi
else 0, by = -yi)
if (dots)
for (tt in xp) symbols(rep(tt, length(yp)),
yp, circles = rep(dotsize, length(yp)),
inches = dotsize, add = TRUE)
else abline(h = yp, v = xp, col = grid, xpd = FALSE)
}
}
tim <- time[s]
srv <- surv[s]
if (conf.int > 0 && conf == "bands") {
blower <- w$lower[s]
bupper <- w$upper[s]
}
if (max(tim) > xlim[2]) {
if (ltype == "s") {
s.last <- srv[tim <= xlim[2] + 1e-06]
s.last <- s.last[length(s.last)]
k <- tim < xlim[2]
tim <- c(tim[k], xlim[2])
srv <- c(srv[k], s.last)
if (conf.int > 0 && conf == "bands") {
low.last <- blower[time <= xlim[2] + 1e-06]
low.last <- low.last[length(low.last)]
up.last <- bupper[time <= xlim[2] + 1e-06]
up.last <- up.last[length(up.last)]
blower <- c(blower[k], low.last)
bupper <- c(bupper[k], up.last)
}
}
else tim[tim > xlim[2]] <- NA
}
if (conf != "bands")
lines(tim, srv, type = ltype, lty = lty[i], col = col[i],
lwd = lwd[i])
if (labelc || conf == "bands")
curves[[i]] <- list(tim, srv)
if (pr) {
zest <- rbind(tim, srv)
dimnames(zest) <- list(c("Time", "Survival"),
rep("", length(srv)))
cat("\nEstimates for ", cl, "\n\n")
print(zest, digits = 3)
}
if (conf.int > 0) {
if (conf == "bands") {
polyg(x = c(tim, rev(tim)), y = c(blower, rev(bupper)),
col = col.fill[i], type = ltype)
}
else {
if (exactci) {
tt <- seq(0, maxtime, time.inc)
v <- survest(fit, newdata = adj, times = tt,
what = what, fun = fun, conf.int = ci,
type = type, conf.type = conf.type)
tt <- v$time
ss <- v$surv
lower <- v$lower
upper <- v$upper
if (!length(ylim))
ylim <- range(ss, na.rm = TRUE)
if (logt)
tt <- logb(ifelse(tt == 0, NA, tt))
}
else {
tt <- as.numeric(dimnames(surv.sum)[[1]])
if (logt)
tt <- logb(tt)
ss <- surv.sum[, stratum, "Survival"]^exp(w$linear.predictors)
se <- surv.sum[, stratum, "std.err"]
ss <- fun(ss)
lower <- fun(cilower(ss, zcrit * se))
upper <- fun(ciupper(ss, zcrit * se))
ss[is.infinite(ss)] <- NA
lower[is.infinite(lower)] <- NA
upper[is.infinite(upper)] <- NA
}
tt <- tt + xd * (i - 1) * 0.01
errbar(tt, ss, upper, lower, add = TRUE, lty = lty[i],
col = col[i])
}
}
if (n.risk) {
if (length(Y <- fit$y)) {
tt <- seq(max(0, xlim[1]), min(maxtime, xlim[2]),
by = time.inc)
ny <- ncol(Y)
if (!length(str <- fit$Strata))
Y <- Y[, ny - 1]
else Y <- Y[unclass(str) == unclass(stratum),
ny - 1]
nrisk <- rev(cumsum(table(cut(-Y, sort(unique(-c(tt,
range(Y) + c(-1, 1))))))[-length(tt) - 1]))
}
else {
if (is.null(surv.sum))
stop("you must use surv=T or y=T in fit to use n.risk=T")
tt <- as.numeric(dimnames(surv.sum)[[1]])
l <- (tt >= xlim[1]) & (tt <= xlim[2])
tt <- tt[l]
nrisk <- surv.sum[l, stratum, 2]
}
tt[1] <- xlim[1]
yd <- ylim[2] - ylim[1]
if (missing(y.n.risk))
y.n.risk <- ylim[1]
yy <- y.n.risk + yd * (nc - i) * sep.n.risk
nri <- nrisk
nri[tt > xlim[2]] <- NA
text(tt[1], yy, nri[1], cex = cex.n.risk, adj = adj.n.risk,
srt = srt.n.risk)
text(tt[-1], yy, nri[-1], cex = cex.n.risk, adj = 1)
text(xlim[2] + xd * 0.025, yy, adj = 0, curve.labels[i],
cex = cex.n.risk)
}
}
}
if (conf == "bands")
for (i in 1:length(y)) lines(curves[[i]][[1]], curves[[i]][[2]],
type = ltype, lty = lty[i], col = col[i], lwd = lwd[i])
if (labelc)
labcurve(curves, curve.labels, type = ltype, lty = lty,
col. = col, lwd = lwd, opts = label.curves)
if (length(adjust))
title(sub = paste("Adjusted to:", adjust), adj = 0, cex = 0.6)
invisible(list(adjust = adjust, curve.labels = curve.labels))
}
environment(survplot2) <- environment(rms:::survplot.rms)
Tested with the first example in rms::survplot using xlim=c(0,26) and xlim=c(0,28). Needed to assign the environment because otherwise you get this error:
Error in Predict(fit, type = "model.frame", np = 5,
factors = rmsArgs(substitute(list(...)))) :
could not find function "rmsArgs"

R | combine plots that use par(mfrow = ...) internally

Take plot.acf as an example. Both acf and pacf call this function internally. How can i plot them side by side?
Example:
TS <- ts.union(mdeaths, fdeaths)
acf(TS)
pacf(TS)
I tried to use par(mfrow = c(2,4)) and layout to combine them, but stats:::plot.acf overwrites this. The expected output would be:
A different approach than my other answer: Plot the ACF using ggplot2.
ggacf <- function(x, ci=0.95, type="correlation", xlab="Lag", ylab=NULL,
ylim=NULL, main=NULL, ci.col="blue", lag.max=NULL) {
x <- as.data.frame(x)
x.acf <- acf(x, plot=F, lag.max=lag.max, type=type)
ci.line <- qnorm((1 - ci) / 2) / sqrt(x.acf$n.used)
d.acf <- data.frame(lag=x.acf$lag, acf=x.acf$acf)
g <- ggplot(d.acf, aes(x=lag, y=acf)) +
geom_hline(yintercept=0) +
geom_segment(aes(xend=lag, yend=0)) +
geom_hline(yintercept=ci.line, color=ci.col, linetype="dashed") +
geom_hline(yintercept=-ci.line, color=ci.col, linetype="dashed") +
theme_bw() +
xlab("Lag") +
ggtitle(ifelse(is.null(main), "", main)) +
if (is.null(ylab))
ylab(ifelse(type=="partial", "PACF", "ACF"))
else
ylab(ylab)
g
}
This seeks to create a similar interface to plot.acf(). Then you can use all of the great features available to ggplot2 plots from the gridExtra package.
library(ggplot2)
library(gridExtra)
grid.arrange(ggacf(lh), ggacf(lh, type="partial"), ncol=2)
Then you get this:
Unfortunately grid.arrange() doesn't work with base graphics, hence the ggplot2 suggestion.
This isn't an ideal solution, but you can redefine what it means to plot an ACF/PACF by defining plot.acf().
First store the existing version.
old.plot.acf <- plot.acf
Now you can use stats:::plot.acf to get the source and copy/paste into the editor. Remove the part that resets mfrow.
plot.acf <- function(x, ci = 0.95, type = "h", xlab = "Lag", ylab = NULL,
ylim = NULL, main = NULL, ci.col = "blue",
ci.type = c("white", "ma"), max.mfrow = 6,
ask = Npgs > 1 && dev.interactive(),
mar = if (nser > 2) c(3, 2, 2, 0.8) else par("mar"),
oma = if (nser > 2) c(1, 1.2, 1, 1) else par("oma"),
mgp = if (nser > 2) c(1.5, 0.6, 0) else par("mgp"),
xpd = par("xpd"), cex.main = if (nser > 2) 1 else
par("cex.main"), verbose = getOption("verbose"), ...)
{
ci.type <- match.arg(ci.type)
if ((nser <- ncol(x$lag)) < 1L)
stop("x$lag must have at least 1 column")
if (is.null(ylab))
ylab <- switch(x$type, correlation = "ACF", covariance = "ACF (cov)",
partial = "Partial ACF")
if (is.null(snames <- x$snames))
snames <- paste("Series ", if (nser == 1L)
x$series
else 1L:nser)
with.ci <- ci > 0 && x$type != "covariance"
with.ci.ma <- with.ci && ci.type == "ma" && x$type == "correlation"
if (with.ci.ma && x$lag[1L, 1L, 1L] != 0L) {
warning("can use ci.type=\"ma\" only if first lag is 0")
with.ci.ma <- FALSE
}
clim0 <- if (with.ci)
qnorm((1 + ci)/2)/sqrt(x$n.used)
else c(0, 0)
Npgs <- 1L
nr <- nser
if (nser > 1L) {
sn.abbr <- if (nser > 2L)
abbreviate(snames)
else snames
if (nser > max.mfrow) {
Npgs <- ceiling(nser/max.mfrow)
nr <- ceiling(nser/Npgs)
}
### NOT INCLUDED: mfrow = rep(nr, 2L)
opar <- par(mar = mar, oma = oma,
mgp = mgp, ask = ask, xpd = xpd, cex.main = cex.main)
on.exit(par(opar))
if (verbose) {
message("par(*) : ", appendLF = FALSE, domain = NA)
str(par("mfrow", "cex", "cex.main", "cex.axis", "cex.lab",
"cex.sub"))
}
}
if (is.null(ylim)) {
ylim <- range(x$acf[, 1L:nser, 1L:nser], na.rm = TRUE)
if (with.ci)
ylim <- range(c(-clim0, clim0, ylim))
if (with.ci.ma) {
for (i in 1L:nser) {
clim <- clim0 * sqrt(cumsum(c(1, 2 * x$acf[-1,
i, i]^2)))
ylim <- range(c(-clim, clim, ylim))
}
}
}
for (I in 1L:Npgs) for (J in 1L:Npgs) {
dev.hold()
iind <- (I - 1) * nr + 1L:nr
jind <- (J - 1) * nr + 1L:nr
if (verbose)
message("Page [", I, ",", J, "]: i =", paste(iind,
collapse = ","), "; j =", paste(jind, collapse = ","),
domain = NA)
for (i in iind) for (j in jind) if (max(i, j) > nser) {
frame()
box(col = "light gray")
}
else {
clim <- if (with.ci.ma && i == j)
clim0 * sqrt(cumsum(c(1, 2 * x$acf[-1, i, j]^2)))
else clim0
plot(x$lag[, i, j], x$acf[, i, j], type = type, xlab = xlab,
ylab = if (j == 1)
ylab
else "", ylim = ylim, ...)
abline(h = 0)
if (with.ci && ci.type == "white")
abline(h = c(clim, -clim), col = ci.col, lty = 2)
else if (with.ci.ma && i == j) {
clim <- clim[-length(clim)]
lines(x$lag[-1, i, j], clim, col = ci.col, lty = 2)
lines(x$lag[-1, i, j], -clim, col = ci.col, lty = 2)
}
title(if (!is.null(main))
main
else if (i == j)
snames[i]
else paste(sn.abbr[i], "&", sn.abbr[j]), line = if (nser >
2)
1
else 2)
}
if (Npgs > 1) {
mtext(paste("[", I, ",", J, "]"), side = 1, line = -0.2,
adj = 1, col = "dark gray", cex = 1, outer = TRUE)
}
dev.flush()
}
invisible()
}
Now that this is defined locally, you can set mfrow as needed, do your plotting, then reset the function or clear it from the namespace.
plot.acf <- old.plot.acf
To avoid also having to change plot.pacf() as well, you can just use acf(..., type="partial"), which gets the PACF.
You can use the PerformanceAnalytics package:
library(PerformanceAnalytics)
chart.ACFplus(TS)

Add additional column colorside bar using heatmap.plus function (or another recommended heat map function)

I am currently using heatmap.plus to draw heatmaps with color side bars in each side (row, and column). An example of a code to plot a heatmap for a matrix of dim 18 by 50 bellow:
m.to.plot = matrix(rnorm(n=18*50,mean=3,sd=2), nrow=18, ncol=50)
colc = rainbow(2)[c(rep(x=2,30), rep(x=1,20))]
tmp = runif(n=18, min=0,max = 1)
rowc = rgb(tmp^1.5+(1-tmp^1.5)*0.742,tmp^1.5+(1-tmp^1.5)*0.742,(1-tmp^1.5)*0.742);
heatmap.plus(m.to.plot,
scale="none",
ColSideColors=colc,
RowSideColors=rowc,
Rowv=NA, Colv=NA,
col=c("green2","red2"))
Such code produce a figure like this:
But what I really want is a two column colored side bar, an example of the 'unfinished' code and it's 'in theory' image would look like this:
m.to.plot = matrix(rnorm(n=18*50,mean=3,sd=2), nrow=18, ncol=50)
colc = rainbow(2)[c(rep(x=2,30), rep(x=1,20))]
tmp = runif(n=18, min=0,max = 1)
rowc = rgb(tmp^1.5+(1-tmp^1.5)*0.742,tmp^1.5+(1-tmp^1.5)*0.742,(1-tmp^1.5)*0.742);
tmp2 = runif(n=50, min=0,max = 1)
extra.colc = rgb(tmp^1.5+(1-tmp^1.5)*0.742,tmp^1.5+(1-tmp^1.5)*0.742,(1-tmp^1.5)*0.742);
Then I need to call heatmap.plus (or change/use another heatmap.plus) such that I can visualize two column colored sided bars in the same plot
And it'd be...
voila!
Any ideas on how to modify heatmap.plus and/or the way I call the function?
Note: the heatmap function I am using is heatmap.plus, taken from bioconductor. A copy of it below (in case someone is interested).
heatmap.plus = function (x, Rowv = NULL, Colv = if (symm) "Rowv" else NULL,
distfun = dist, hclustfun = hclust, reorderfun = function(d,w) reorder(d, w),
add.expr, symm = FALSE, revC = identical(Colv, "Rowv"), scale = c("row", "column", "none"), na.rm = TRUE,
margins = c(5, 5), ColSideColors, RowSideColors, cexRow = 0.2 +
1/log10(nr), cexCol = 0.2 + 1/log10(nc), labRow = NULL,
labCol = NULL, cRow=NULL, cCol=NULL, main = NULL, xlab = NULL, ylab = NULL, keep.dendro = FALSE,
verbose = getOption("verbose"), ...)
{
scale <- if (symm && missing(scale))
"none"
else match.arg(scale)
if (length(di <- dim(x)) != 2 || !is.numeric(x))
stop("'x' must be a numeric matrix")
nr <- di[1]
nc <- di[2]
if (nr <= 1 || nc <= 1)
stop("'x' must have at least 2 rows and 2 columns")
if (!is.numeric(margins) || length(margins) != 2)
stop("'margins' must be a numeric vector of length 2")
doRdend <- !identical(Rowv, NA)
doCdend <- !identical(Colv, NA)
if (is.null(Rowv))
Rowv <- rowMeans(x, na.rm = na.rm)
if (is.null(Colv))
Colv <- colMeans(x, na.rm = na.rm)
if (doRdend) {
if (inherits(Rowv, "dendrogram"))
ddr <- Rowv
else {
hcr <- hclustfun(distfun(x))
ddr <- as.dendrogram(hcr)
if (!is.logical(Rowv) || Rowv)
ddr <- reorderfun(ddr, Rowv)
}
if (nr != length(rowInd <- order.dendrogram(ddr)))
stop("row dendrogram ordering gave index of wrong length")
}
else rowInd <- 1:nr
if (doCdend) {
if (inherits(Colv, "dendrogram"))
ddc <- Colv
else if (identical(Colv, "Rowv")) {
if (nr != nc)
stop("Colv = \"Rowv\" but nrow(x) != ncol(x)")
ddc <- ddr
}
else {
hcc <- hclustfun(distfun(if (symm)
x
else t(x)))
ddc <- as.dendrogram(hcc)
if (!is.logical(Colv) || Colv)
ddc <- reorderfun(ddc, Colv)
}
if (nc != length(colInd <- order.dendrogram(ddc)))
stop("column dendrogram ordering gave index of wrong length")
}
else colInd <- 1:nc
x <- x[rowInd, colInd]
labRow <- if (is.null(labRow))
if (is.null(rownames(x)))
(1:nr)[rowInd]
else rownames(x)
else labRow[rowInd]
labCol <- if (is.null(labCol))
if (is.null(colnames(x)))
(1:nc)[colInd]
else colnames(x)
else labCol[colInd]
if (scale == "row") {
x <- sweep(x, 1, rowMeans(x, na.rm = na.rm))
sx <- apply(x, 1, sd, na.rm = na.rm)
x <- sweep(x, 1, sx, "/")
}
else if (scale == "column") {
x <- sweep(x, 2, colMeans(x, na.rm = na.rm))
sx <- apply(x, 2, sd, na.rm = na.rm)
x <- sweep(x, 2, sx, "/")
}
lmat <- rbind(c(NA, 3), 2:1)
lwid <- c(if (doRdend) 1 else 0.05, 4)
lhei <- c((if (doCdend) 1 else 0.05) + if (!is.null(main)) 0.2 else 0,
4)
if (!missing(ColSideColors))
{
lmat <- rbind(lmat[1, ] + 1, c(NA, 1), lmat[2, ] + 1)
lhei <- c(lhei[1], 0.125/par()$fin[2]*10, lhei[2])
}
if (!missing(RowSideColors)) {
lmat <- cbind(lmat[, 1] + 1, c(rep(NA, nrow(lmat) - 1),
1), lmat[, 2] + 1)
lwid <- c(lwid[1], 0.135/par()$fin[1]*10, lwid[2])
}
lmat[is.na(lmat)] <- 0
if (verbose) {
cat("layout: widths = ", lwid, ", heights = ", lhei,
"; lmat=\n")
print(lmat)
}
op <- par(no.readonly = TRUE)
on.exit(par(op))
layout(lmat, widths = lwid, heights = lhei, respect = FALSE)
if (!missing(RowSideColors)) {
par(mar = c(margins[1L], 0, 0, 0.5))
image(rbind(1L:nr), col = RowSideColors[rowInd], axes = FALSE)
}
if (!missing(ColSideColors)) {
par(mar = c(0.5, 0, 0, margins[2L]))
image(cbind(1L:nc), col = ColSideColors[colInd], axes = FALSE)
}
par(mar = c(margins[1], 0, 0, margins[2]))
if (!symm || scale != "none") {
x <- t(x)
}
if (revC) {
iy <- nr:1
ddr <- rev(ddr)
x <- x[, iy]
}
else iy <- 1:nr
image(1:nc, 1:nr, x, xlim = 0.5 + c(0, nc), ylim = 0.5 +
c(0, nr), axes = FALSE, xlab = "", ylab = "", ...)
axis(1, 1:nc, labels = labCol, las = 2, line = -0.5, tick = 0,
cex.axis = cexCol)
if (!is.null(xlab))
mtext(xlab, side = 1, line = margins[1] - 1.25)
axis(4, iy, labels = labRow, las = 2, line = -0.5, tick = 0,
cex.axis = cexRow)
if (!is.null(ylab))
mtext(ylab, side = 4, line = margins[2] - 1.25)
if (!missing(add.expr))
eval(substitute(add.expr))
par(mar = c(margins[1], 0, 0, 0))
if (doRdend)
plot(ddr, horiz = TRUE, axes = FALSE, yaxs = "i", leaflab = "none")
else frame()
par(mar = c(0, 0, if (!is.null(main)) 1 else 0, margins[2]))
if (doCdend)
plot(ddc, axes = FALSE, xaxs = "i", leaflab = "none")
else if (!is.null(main))
frame()
if (!is.null(main))
title(main, cex.main = 1.5 * op[["cex.main"]])
invisible(list(rowInd = rowInd, colInd = colInd, Rowv = if (keep.dendro &&
doRdend) ddr, Colv = if (keep.dendro && doCdend) ddc))
}
You can use a matrix for ColSideColor instead of a vector.
For example:
you have two vectors :
A B
Red Blue
green black
Red yellow
purple Blue
create a matrix:
colormatrix <- cbind(A,B)
and use it as for ColSideColor then you will have two ColSideColors in your sample code: instead
of colc use colormatrix.
heatmap.plus(m.to.plot,
scale="none",
ColSideColors=colormatrix,
RowSideColors=rowc,
Rowv=NA, Colv=NA,
col=c("green2","red2"))

Resources