Remove Control Limits With qcc Package in R (Quality Control Charts) - r

I need to remove the lower control limit and center line (and their labels) from my control chart.
Here's the code:
# install.packages('qcc')
library(qcc)
nonconforming <- c(3, 4, 6, 5, 2, 8, 9, 4, 2, 6, 4, 8, 0, 7, 20, 6, 1, 5, 7)
samplesize <- rep(50, 19)
control <- qcc(nonconforming, type = "p", samplesize, plot = "FALSE")
warn.limits <- limits.p(control$center, control$std.dev, control$sizes, 2)
par(mar = c(5, 3, 1, 3), bg = "blue")
plot(control, restore.par = FALSE, title = "P Chart for Medical Insurance Claims",
xlab = "Day", ylab = "Proportion Defective")
abline(h = warn.limits, lty = 3, col = "blue")
v2 <- c("LWL", "UWL") # the labels for warn.limits
mtext(side = 4, text = v2, at = warn.limits, col = "blue", las = 2)

This approach seems more like a "hack" than an answer and it throws a warning:
control$center <- NULL
control$limits <- NULL
plot(control, add.stats = FALSE)

Not a QC expert by any means but would this work for you? Looking at the qcc function it seems to control what needs to be plotted, so what i've done here is manipulate the limits of the LCL and CENTRE lines. I then changed the plot function to plot between some y limits which does not cover the -1 value. The description unfortunately reflects the manipulated limit values of -1.
control$limits[1] <- -1
control$center <- -1
plot(control, restore.par = FALSE, title = "P Chart for Medical Insurance Claims",
xlab = "Day", ylab = "Proportion Defective", ylim=c(0.0,0.4))

The following function will do the required chart, and you don't need to change your control object, neither to know the control's limits. Load the function, then just call:
plot.qcc2(control, restore.par = FALSE, title = "P Chart for Medical Insurance Claims", + xlab = "Day", ylab = "Proportion Defective")
Function:
#Function plotting only UCL:
plot.qcc2 <- function (x, add.stats = TRUE, chart.all = TRUE, label.limits = c( "UCL"), title, xlab, ylab, ylim, axes.las = 0, digits = getOption("digits"),
restore.par = TRUE, ...)
{
object <- x
if ((missing(object)) | (!inherits(object, "qcc")))
stop("an object of class `qcc' is required")
type <- object$type
std.dev <- object$std.dev
data.name <- object$data.name
center <- object$center
stats <- object$statistics
limits <- object$limits
lcl <- limits[, 1]
ucl <- limits[, 2]
newstats <- object$newstats
newdata.name <- object$newdata.name
violations <- object$violations
if (chart.all) {
statistics <- c(stats, newstats)
indices <- 1:length(statistics)
}
else {
if (is.null(newstats)) {
statistics <- stats
indices <- 1:length(statistics)
}
else {
statistics <- newstats
indices <- seq(length(stats) + 1, length(stats) +
length(newstats))
}
}
if (missing(title)) {
if (is.null(newstats))
main.title <- paste(type, "Chart\nfor", data.name)
else if (chart.all)
main.title <- paste(type, "Chart\nfor", data.name,
"and", newdata.name)
else main.title <- paste(type, "Chart\nfor", newdata.name)
}
else main.title <- paste(title)
oldpar <- par(bg = qcc.options("bg.margin"), cex = qcc.options("cex"),
mar = if (add.stats)
pmax(par("mar"), c(8.5, 0, 0, 0))
else par("mar"), no.readonly = TRUE)
if (restore.par)
on.exit(par(oldpar))
plot(indices, statistics, type = "n", ylim = if (!missing(ylim))
ylim
else range(statistics, limits, center), ylab = if (missing(ylab))
"Group summary statistics"
else ylab, xlab = if (missing(xlab))
"Group"
else xlab, axes = FALSE, main = main.title)
rect(par("usr")[1], par("usr")[3], par("usr")[2], par("usr")[4],
col = qcc.options("bg.figure"))
axis(1, at = indices, las = axes.las, labels = if (is.null(names(statistics)))
as.character(indices)
else names(statistics))
axis(2, las = axes.las)
box()
lines(indices, statistics, type = "b", pch = 20)
if (length(center) == 1)
alpha <- 1
else lines(indices, c(center, center[length(center)]), type = "s")
if (length(lcl) == 1) {
abline(h = ucl, lty = 2)
}
else {
lines(indices, ucl[indices], type = "s", lty = 2)
}
mtext(label.limits, side = 4, at = c(rev(ucl)[1],rev(ucl)[1]),
las = 1, line = 0.1, col = gray(0.3))
if (is.null(qcc.options("violating.runs")))
stop(".qcc.options$violating.runs undefined. See help(qcc.options).")
if (length(violations$violating.runs)) {
v <- violations$violating.runs
if (!chart.all & !is.null(newstats)) {
v <- v - length(stats)
v <- v[v > 0]
}
points(indices[v], statistics[v], col = qcc.options("violating.runs")$col,
pch = qcc.options("violating.runs")$pch)
}
if (is.null(qcc.options("beyond.limits")))
stop(".qcc.options$beyond.limits undefined. See help(qcc.options).")
if (length(violations$beyond.limits)) {
v <- violations$beyond.limits
if (!chart.all & !is.null(newstats)) {
v <- v - length(stats)
v <- v[v > 0]
}
points(indices[v], statistics[v], col = qcc.options("beyond.limits")$col,
pch = qcc.options("beyond.limits")$pch)
}
if (chart.all & (!is.null(newstats))) {
len.obj.stats <- length(object$statistics)
len.new.stats <- length(statistics) - len.obj.stats
abline(v = len.obj.stats + 0.5, lty = 3)
mtext(paste("Calibration data in", data.name), at = len.obj.stats/2,
adj = 0.5, cex = 0.8)
mtext(paste("New data in", object$newdata.name), at = len.obj.stats +
len.new.stats/2, adj = 0.5, cex = 0.8)
}
if (add.stats) {
plt <- par()$plt
usr <- par()$usr
px <- diff(usr[1:2])/diff(plt[1:2])
xfig <- c(usr[1] - px * plt[1], usr[2] + px * (1 - plt[2]))
at.col <- xfig[1] + diff(xfig[1:2]) * c(0.1, 0.4, 0.65)
mtext(paste("Number of groups = ", length(statistics),
sep = ""), side = 1, line = 5, adj = 0, at = at.col[1],
font = qcc.options("font.stats"), cex = qcc.options("cex.stats"))
center <- object$center
if (length(center) == 1) {
mtext(paste("Center = ", signif(center[1], digits),
sep = ""), side = 1, line = 6, adj = 0, at = at.col[1],
font = qcc.options("font.stats"), cex = qcc.options("cex.stats"))
}
else {
mtext("Center is variable", side = 1, line = 6, adj = 0,
at = at.col[1], qcc.options("font.stats"), cex = qcc.options("cex.stats"))
}
mtext(paste("StdDev = ", signif(std.dev, digits), sep = ""),
side = 1, line = 7, adj = 0, at = at.col[1], font = qcc.options("font.stats"),
cex = qcc.options("cex.stats"))
if (length(unique(lcl)) == 1)
alpha <- 0
#mtext(paste("LCL = ", signif(lcl[1], digits), sep = ""),
# side = 1, line = 6, adj = 0, at = at.col[2],
# font = qcc.options("font.stats"), cex = qcc.options("cex.stats"))
else mtext("LCL is variable", side = 1, line = 6, adj = 0,
at = at.col[2], font = qcc.options("font.stats"),
cex = qcc.options("cex.stats"))
if (length(unique(ucl)) == 1)
mtext(paste("UCL = ", signif(ucl[1], digits), sep = ""),
side = 1, line = 7, adj = 0, at = at.col[2],
font = qcc.options("font.stats"), cex = qcc.options("cex.stats"))
else mtext("UCL is variable", side = 1, line = 7, adj = 0,
at = at.col[2], font = qcc.options("font.stats"),
cex = qcc.options("cex.stats"))
if (!is.null(violations)) {
mtext(paste("Number beyond limits =", length(unique(violations$beyond.limits))),
side = 1, line = 6, adj = 0, at = at.col[3],
font = qcc.options("font.stats"), cex = qcc.options("cex.stats"))
mtext(paste("Number violating runs =", length(unique(violations$violating.runs))),
side = 1, line = 7, adj = 0, at = at.col[3],
font = qcc.options("font.stats"), cex = qcc.options("cex.stats"))
}
}
invisible()
}

Related

R; package {stats}; function {ts.plot}; change x-axis labeles

I need to change the x-axis labels so they are words instead of numerals. Currently, the x-axis goes 1, 2, 3, etc. I would like it to go "Placement", "Fresh", etc.
trendplot <- function(timeseries, color, index, first = FALSE, w = 4, add_main = ""){
if (first) {
plot.ts(timeseries[, index], col = color, lwd = w,
ylim = c(-2, 2),
ylab = "Scaled Relative Abundance",
xlab = "Stage",
main = paste0("Trend Plots", add_main)) # gsub(".", " ", colnames(timeseries)[index], fixed = TRUE)
} else {
lines(timeseries[, index], col = color, lwd = w)
}
}
Update:
This code works for what I wanted it be.
stages<-c('Placement','Fresh','Bloat One','Bloat Two','Post-Bloat One','Post-Bloat Two')
trendplot <- function(timeseries, color, index, first = FALSE, w = 4, add_main = ""){
if (first) {
plot.ts(timeseries[, index], col = color, lwd = w, axes = FALSE,
ylim = c(-2, 2),
ylab = "Scaled Measurement",
xlab = "Time Point",
main = paste0("Trend Plots", add_main)) # gsub(".", " ", colnames(timeseries)[index], fixed = TRUE)+
} else {
lines(timeseries[, index], col = color, lwd = w)
}
{axis(1, at=1:6, labels=stages, cex.axis=0.5)}
}

Label a looped plot in R

I am using a loop for plotting the histogram, group by different values of column_a at once which works perfectly fine. Here's the code:
par(ask=F)
for (i in unique(Data$column_a)) {
dat <- Data[Data$column_a== i, ]
plotdist(dat$count,histo = TRUE, demp = TRUE, discrete = T,
pch = 16, col = "dodgerblue1")
}
The only problem is that I cannot label each figure relative to column_a value to differentiate the figures from on another.
Thanks in advance for the help.
my data consists of number of losses with the column name of "count" with 3 distinct value in column_a(R,I,F)). and I want to plot the histogram of number of losses for these three values.
A somewhat hacky solution would be to alter the function itself.
Below is the alteret function, which uncludes the title argument (and only works for the configuration you had in your question!)
plotdist_alt <- function (data, distr, para, histo = TRUE, breaks = "default",
demp = FALSE, discrete, title = "default", ...)
{
def.par <- par(no.readonly = TRUE)
if (missing(data) || !is.vector(data, mode = "numeric"))
stop("data must be a numeric vector")
if ((missing(distr) & !missing(para)) || (missing(distr) &
!missing(para)))
stop("distr and para must defined")
if (!histo & !demp)
stop("one the arguments histo and demp must be put to TRUE")
xlim <- c(min(data), max(data))
s <- sort(data)
n <- length(data)
if (missing(distr)) {
par(mfrow = c(1, 2))
if (missing(discrete))
discrete <- FALSE
if (!discrete) {
obsp <- ppoints(s)
if (histo) {
if (demp) {
if (breaks == "default")
h <- hist(data, freq = FALSE, xlab = "Data",
main = "Empirical density", ...)
else h <- hist(data, freq = FALSE, xlab = "Data",
main = "Empirical density", breaks = breaks,
...)
lines(density(data)$x, density(data)$y, lty = 2,
col = "black")
}
else {
if (breaks == "default")
h <- hist(data, freq = FALSE, xlab = "Data",
main = "Histogram", ...)
else h <- hist(data, freq = FALSE, xlab = "Data",
main = "Histogram", breaks = breaks,
...)
}
}
else {
h <- hist(data, freq = FALSE, xlab = "Data",
main = "Histogram", plot = FALSE, ...)
plot(density(data)$x, density(data)$y, lty = 1,
col = "black", type = "l", xlab = "Data",
main = paste("Empirical density"), ylab = "Density",
...)
}
plot(s, obsp, main = paste("Cumulative distribution"),
xlab = "Data", xlim = c(h$breaks[1], h$breaks[length(h$breaks)]),
ylab = "CDF", ...)
}
else {
if (breaks != "default")
warning("Breaks are\tnot taken into account for discrete data")
t <- table(data)
xval <- as.numeric(names(t))
ydobs <- as.vector(t)/n
ydmax <- max(ydobs)
plot(xval, ydobs, type = "h", xlim = xlim,
ylim = c(0, ydmax), main = paste0("Empirical distribution ", title),
xlab = "Data", ylab = "Density",
...)
ycdfobs <- cumsum(ydobs)
plot(xval, ycdfobs, type = "p", xlim = xlim,
ylim = c(0, 1), main = paste0("Empirical CDFs ", title),
xlab = "Data", ylab = "CDF", ...)
}
}
else {
if (!is.character(distr))
distname <- substring(as.character(match.call()$distr),
2)
else distname <- distr
if (!is.list(para))
stop("'para' must be a named list")
ddistname <- paste("d", distname, sep = "")
if (!exists(ddistname, mode = "function"))
stop(paste("The ", ddistname, " function must be defined"))
pdistname <- paste("p", distname, sep = "")
if (!exists(pdistname, mode = "function"))
stop(paste("The ", pdistname, " function must be defined"))
qdistname <- paste("q", distname, sep = "")
if (!exists(qdistname, mode = "function"))
stop(paste("The ", qdistname, " function must be defined"))
densfun <- get(ddistname, mode = "function")
nm <- names(para)
f <- formals(densfun)
args <- names(f)
m <- match(nm, args)
if (any(is.na(m)))
stop(paste("'para' specifies names which are not arguments to ",
ddistname))
if (missing(discrete)) {
if (is.element(distname, c("binom", "nbinom",
"geom", "hyper", "pois")))
discrete <- TRUE
else discrete <- FALSE
}
if (!discrete) {
par(mfrow = c(2, 2))
obsp <- ppoints(s)
if (breaks == "default")
h <- hist(data, plot = FALSE)
else h <- hist(data, breaks = breaks, plot = FALSE,
...)
xhist <- seq(min(h$breaks), max(h$breaks), length = 1000)
yhist <- do.call(ddistname, c(list(xhist), as.list(para)))
if (length(yhist) != length(xhist))
stop("problem when computing densities.")
ymax <- ifelse(is.finite(max(yhist)), max(max(h$density),
max(yhist)), max(h$density))
if (histo) {
hist(data, freq = FALSE, xlab = "Data",
ylim = c(0, ymax), breaks = h$breaks, main = paste("Empirical and theoretical dens."),
...)
if (demp) {
lines(density(data)$x, density(data)$y, lty = 2,
col = "black")
}
}
else plot(density(data)$x, density(data)$y, lty = 2,
col = "black", type = "l", xlab = "Data",
main = paste("Empirical and theoretical dens."),
ylab = "Density", xlim = c(min(h$breaks),
max(h$breaks)), ...)
if (demp)
legend("topright", bty = "n", lty = c(2,
1), col = c("black", "red"), legend = c("empirical",
"theoretical"), bg = "white", cex = 0.7)
lines(xhist, yhist, lty = 1, col = "red")
theoq <- do.call(qdistname, c(list(obsp), as.list(para)))
if (length(theoq) != length(obsp))
stop("problem when computing quantities.")
plot(theoq, s, main = " Q-Q plot", xlab = "Theoretical quantiles",
ylab = "Empirical quantiles", ...)
abline(0, 1)
xmin <- h$breaks[1]
xmax <- h$breaks[length(h$breaks)]
if (length(s) != length(obsp))
stop("problem when computing probabilities.")
plot(s, obsp, main = paste("Empirical and theoretical CDFs"),
xlab = "Data", ylab = "CDF", xlim = c(xmin,
xmax), ...)
sfin <- seq(xmin, xmax, by = (xmax - xmin)/100)
theopfin <- do.call(pdistname, c(list(sfin), as.list(para)))
lines(sfin, theopfin, lty = 1, col = "red")
theop <- do.call(pdistname, c(list(s), as.list(para)))
if (length(theop) != length(obsp))
stop("problem when computing probabilities.")
plot(theop, obsp, main = "P-P plot", xlab = "Theoretical probabilities",
ylab = "Empirical probabilities", ...)
abline(0, 1)
}
else {
par(mfrow = c(1, 2))
if (breaks != "default")
warning("Breaks are not taken into account for discrete distributions")
t <- table(data)
xval <- as.numeric(names(t))
xvalfin <- seq(min(xval), max(xval), by = 1)
xlinesdec <- min((max(xval) - min(xval))/30, 0.4)
yd <- do.call(ddistname, c(list(xvalfin), as.list(para)))
if (length(yd) != length(xvalfin))
stop("problem when computing density points.")
ydobs <- as.vector(t)/n
ydmax <- max(yd, ydobs)
plot(xvalfin + xlinesdec, yd, type = "h", xlim = c(min(xval),
max(xval) + xlinesdec), ylim = c(0, ydmax), lty = 1,
col = "red", main = "Emp. and theo. distr.",
xlab = "Data", ylab = "Density",
...)
points(xval, ydobs, type = "h", lty = 1, col = "black",
...)
legend("topright", lty = c(1, 1), col = c("black",
"red"), legend = c("empirical", paste("theoretical")),
bty = "o", bg = "white", cex = 0.6,
...)
ycdf <- do.call(pdistname, c(list(xvalfin), as.list(para)))
if (length(ycdf) != length(xvalfin))
stop("problem when computing probabilities.")
plot(xvalfin, ycdf, type = "s", xlim = c(min(xval),
max(xval) + xlinesdec), ylim = c(0, 1), lty = 1,
col = "red", main = "Emp. and theo. CDFs",
xlab = "Data", ylab = "CDF", ...)
ycdfobs <- cumsum(ydobs)
points(xval, ycdfobs, type = "p", col = "black",
...)
legend("bottomright", lty = c(1, 1), col = c("black",
"red"), legend = c("empirical", paste("theoretical")),
bty = "o", bg = "white", cex = 0.6,
...)
}
}
par(def.par)
invisible()
}
To now add a title to your plot, simply use this:
par(ask=F)
for (i in unique(Data$column_a)) {
dat <- Data[Data$column_a== i, ]
plotdist_alt(dat$count,histo = TRUE, demp = TRUE, discrete = T,
pch = 16, col = "dodgerblue1", title = i)
}
Edit: Added dummy data to test the provided loop.
df <- data.frame(column_a = rep(c("a", "b"), each = 50),
count = sample(1:1000, 100, replace = T))
par(ask=F)
for (i in unique(df$column_a)) {
dat <- df[df$column_a== i, ]
plotdist_alt(dat$count,histo = TRUE, demp = TRUE, discrete = T,
pch = 16, col = "dodgerblue1", title = i)
}

How to plot two series in one single plot with different y-axis in plot.xts in R (current version of xts)

I'm trying to recreate this plot that I made with the old (pre 0.10-0) version of xts. Here's some example data:
library(xts) # Run using xts_0.9-7
set.seed(190)
modelo_1 <- arima.sim(n = 252*8,list(ar = c(.99999),sd = sqrt(0.5)))
set.seed(256)
modelo_2 <- arima.sim(n = 252*8,list(ar = c(.9999),sd = sqrt(0.75)))
d1 <- as.Date("2008-01-01")
series_1 <- xts(modelo_1, seq(d1, by = "days", along.with = modelo_1))
series_2 <- xts(modelo_2, seq(d1, by = "days", along.with = modelo_2))
The code below uses the old version to create the graph I want.
par(mar = c(5, 4, 4, 4))
plot(series_1, las = 1, main = "", mar = c(5, 2, 2, 5))
par(new = TRUE)
plot(series_2, col = 2, axes = FALSE, main = "Two Series")
axis(4, las = 1)
lnames <- c("Series 1 (left)", "Series 2 (right)")
legend("top", legend = lnames, lty = 1, cex = 0.85, col = c(1, 2), bty = "n")
How can I create this plot with the new version of plot.xts()? Here's what I've tried, but both series use the same axis.
plot(cbind(series_1, series_2))
lnames <- c("Series 1", "Series 2")
addLegend("bottom", legend.names = lnames, ncol = 2, lty = 1, lwd = 1, cex = 1)
The old way of doing this is not working anymore, because of this issue.
plot(series_1, las = 1, yaxis.right = FALSE,yaxis.same = FALSE)
par(new = TRUE)
plot(series_2, col = 2, bty = "n", xaxt = "n", yaxt = "n", xlab = "", ylab = "")
axis(4, las = 1)
lnames <- c("Series 1", "Series 2")
legend("topleft", legend = lnames, col = 1:2, lty = 1, cex = 0.85)
I don't speak English very well so forgive me.
Below is the code with the change so that it plots as it was before.
note that the only change was to put the index as x in the plot function. Same index for both plot() functions
library(xts) # Run using xts_0.9-7
set.seed(190)
modelo_1 <- arima.sim(n = 252*8,list(ar = c(.99999),sd = sqrt(0.5)))
set.seed(256)
modelo_2 <- arima.sim(n = 252*8,list(ar = c(.9999),sd = sqrt(0.75)))
d1 <- as.Date("2008-01-01")
series_1 <- xts(modelo_1, seq(d1, by = "days", along.with = modelo_1))
series_2 <- xts(modelo_2, seq(d1, by = "days", along.with = modelo_2))
#O código abaixo usa a versão antiga para criar o gráfico que eu quero.
plot.new()
par(mar = c(5, 4, 4, 4))
plot(index(series_1),series_1, las = 1, main = "",
type = 'l', mar = c(5, 2, 2, 5))
par(new = TRUE)
plot(index(series_1),series_2, col = 2, axes = FALSE,
type = 'l', main = "Two Series")
axis(4, las = 1)
lnames <- c("Series 1 (left)", "Series 2 (right)")
legend("top", legend = lnames, lty = 1, cex = 0.85, col = c(1, 2), bty = "n")

How to control Control the legend SOM codes plot - plot.kohonen

I would like to access the legend on a kohonen SOM plot. For example this code ...
library("kohonen")
data("wines")
wines.sc <- scale(wines)
set.seed(7)
wine.som <- som(wines.sc, grid = somgrid(5, 4, "hexagonal"))
plot(wine.som, main = "Wine data",shape="straight")
... creates a nice plot with a legend of the 13 variables in a 3 column 5 row format. How do I access the legend controls on this plot to make it say 2 columns by 7 rows or perhaps 4 columns with4 rows? Perhaps I need to somehow turn the legend off (not sure how) and create my own legend in the outer margin?
Download the myplot.kohcodes function here and save it in your working directory as myplot.kohcodes.r.
Set the number of columns in the legend using the ncolsleg parameter.
Then, run the code:
library("kohonen")
data("wines")
wines.sc <- scale(wines)
set.seed(7)
wine.som <- som(wines.sc, grid = somgrid(5, 4, "hexagonal"))
source("myplot.kohcodes.r")
myplot.kohcodes(wine.som, main = "Wine data", keepMargins=FALSE,
palette.name=NULL, whatmap = NULL, codeRendering = NULL,
bgcol = NULL, ncolsleg=2)
A note. If the legend width is greater than the plot width, myplot.kohcodes reduces the cex parameter until the legend width is lower that the plot width.
myplot.kohcodes <- function (x, whatmap, main, palette.name, bgcol, codeRendering,
keepMargins, shape = c("round", "straight"), border = "black", ncolsleg=3,
...)
{
if (!keepMargins) {
opar <- par(c("mar"))
on.exit(par(opar))
}
if (is.null(palette.name))
palette.name <- terrain.colors
whatmap <- check.whatmap(x, whatmap)
nmaps <- length(whatmap)
if (is.list(x$codes)) {
for (i in 1:nmaps) {
huhn <- list(whatmap = 1, grid = x$grid)
huhn$codes <- getCodes(x, whatmap[i])
if (length(main) == length(x$codes)) {
main.title <- main[whatmap[i]]
}
else {
if (length(main) == nmaps) {
main.title <- main[i]
}
else {
if (length(main) == 1) {
main.title <- main
}
else {
if (is.null(main)) {
if (!is.null(names(x$codes))) {
main.title <- names(x$codes)[whatmap[i]]
}
else {
main.title <- "Codes plot"
}
}
}
}
}
if (length(codeRendering) == length(x$codes)) {
cR <- codeRendering[whatmap[i]]
}
else {
if (length(codeRendering) == nmaps) {
cR <- codeRendering[i]
}
else {
cR <- codeRendering
}
}
myplot.kohcodes(huhn, main = main.title, palette.name = palette.name,
bgcol = bgcol, whatmap = NULL, codeRendering = cR,
keepMargins = TRUE, shape = shape, border = border, ncolsleg,
...)
}
}
else {
codes <- x$codes
nvars <- ncol(codes)
maxlegendcols <- 3
ncols <- ncolsleg
print(ncolsleg)
if (is.null(codeRendering))
codeRendering <- ifelse(nvars < 15, "segments", "lines")
margins <- rep(0.6, 4)
if (!is.null(main))
margins[3] <- margins[3] + 2
par(mar = margins)
if (codeRendering == "segments" & !is.null(colnames(codes))) {
kohonen:::plot.somgrid(x$grid, ylim = c(max(x$grid$pts[, 2]) + min(x$grid$pts[,
2]), -2))
current.plot <- par("mfg")
plot.width <- diff(par("usr")[1:2])
cex <- 1
leg.result <- legend(x = mean(x$grid$pts[, 1]), xjust = 0.5,
y = 0, yjust = 1, legend = colnames(codes), cex = cex,
plot = FALSE, ncol = ncols, fill = palette.name(nvars))
while (leg.result$rect$w > plot.width) {
cex <- cex * 0.9
leg.result <- legend(x = mean(x$grid$pts[, 1]),
xjust = 0.5, y = 0, yjust = 1, legend = colnames(codes),
cex = cex, plot = FALSE, ncol = ncols, fill = palette.name(nvars))
}
leg.result <- legend(x = mean(x$grid$pts[, 1]), xjust = 0.5,
y = 0, yjust = 1, cex = cex, legend = colnames(codes),
plot = FALSE, ncol = ncols, fill = palette.name(nvars),
...)
par(mfg = current.plot)
kohonen:::plot.somgrid(x$grid, ylim = c(max(x$grid$pts[, 2]) + min(x$grid$pts[,
2]), -leg.result$rect$h))
legend(x = mean(x$grid$pts[, 1]), xjust = 0.5, y = 0,
yjust = 1, cex = cex, plot = TRUE, legend = colnames(codes),
ncol = ncols, fill = palette.name(nvars), ...)
}
else {
plot(x$grid, ...)
}
title.y <- max(x$grid$pts[, 2]) + 1.2
if (title.y > par("usr")[4] - 0.2) {
title(main)
}
else {
text(mean(range(x$grid$pts[, 1])), title.y, main,
adj = 0.5, cex = par("cex.main"), font = par("font.main"))
}
if (is.null(bgcol))
bgcol <- "transparent"
shape <- match.arg(shape)
sym <- ifelse(shape == "round", "circle", ifelse(x$grid$topo ==
"rectangular", "square", "hexagon"))
switch(sym, circle = symbols(x$grid$pts[, 1], x$grid$pts[,
2], circles = rep(0.5, nrow(x$grid$pts)), inches = FALSE,
add = TRUE, fg = border, bg = bgcol), hexagon = hexagons(x$grid$pts[,
1], x$grid$pts[, 2], unitcell = 1, col = bgcol, border = border),
square = symbols(x$grid$pts[, 1], x$grid$pts[, 2],
squares = rep(1, nrow(x$grid$pts)), inches = FALSE,
add = TRUE, fg = border, bg = bgcol))
if (codeRendering == "lines") {
yrange <- range(codes)
codes <- codes - mean(yrange)
}
else {
codemins <- apply(codes, 2, min)
codes <- sweep(codes, 2, codemins)
}
switch(codeRendering, segments = {
stars(codes, locations = x$grid$pts, labels = NULL,
len = 0.4, add = TRUE, col.segments = palette.name(nvars),
draw.segments = TRUE)
}, lines = {
for (i in 1:nrow(x$grid$pts)) {
if (yrange[1] < 0 & yrange[2] > 0) {
lines(seq(x$grid$pts[i, 1] - 0.4, x$grid$pts[i,
1] + 0.4, length = 2), rep(x$grid$pts[i,
2], 2), col = "gray")
}
lines(seq(x$grid$pts[i, 1] - 0.4, x$grid$pts[i,
1] + 0.4, length = ncol(codes)), x$grid$pts[i,
2] + codes[i, ] * 0.8/diff(yrange), col = "red")
}
}, stars = stars(codes, locations = x$grid$pts, labels = NULL,
len = 0.4, add = TRUE))
}
invisible()
}

Add a common legend to a partitioned plot

I would like to make a partitioned plot in R with a common legend.
Here's an example data:
set.seed(1)
replicates <- 4
df <- data.frame(y = rep(rnorm(100),replicates), x = rep(rnorm(100),replicates),
replicate = c(sapply(1:replicates,function(x) rep(x,100))))
par(mfcol = c(4,4),
mar = c(3,3,0.5,0.5), oma = rep(1,4))
for(i in 1:replicates){
for(j in 1:replicates){
plot(df$x[which(df$replicate == i)], df$x[which(df$replicate == j)], xlab = "", ylab = "")
title(xlab = paste("replicate", i, sep = " "), ylab = paste("replicate", j, sep = " "), line = 2)
}
}
The common legend, which I would like to appear at the bottom, should be:
legend(legend = "measurements", pch = 16, col = "gray")
Use layout:
par(mar = c(3,3,0.5,0.5), oma = rep(1,4))
layout(rbind(matrix(1:16, 4), rep(17, 4)), heights = c(rep(1, 4), 0.5))
for(i in 1:replicates){
for(j in 1:replicates){
plot(df$x[which(df$replicate == i)], df$x[which(df$replicate == j)], xlab = "", ylab = "")
title(xlab = paste("replicate", i, sep = " "), ylab = paste("replicate", j, sep = " "), line = 2)
}
}
par(mar = c(0,0,0,0))
plot.new()
legend(x = "center", legend = "measurements", pch = 16, col = "gray")

Resources