I carried out a post-hoc Tukey test on an ANOVA and then I made a plot of the results. I can't seem to change my x axis title or my y axis title. I get this error:
Error in plot.default(c(xi[, "lwr"], xi[, "upr"]), rep.int(yvals, 2L), :
formal argument "xlab" matched by multiple actual arguments
This is my relevant code:
tuk <- TukeyHSD(final)
plot(tuk,xlab="Differences in mean departure times", ylab="Comparisons")
I also need to change the y axis tick mark labels but I don't know how.
Thanks.
So because of how they wrote the plot() method for TukeyHSD class object you can not change the axis labels by default, this detail is buried in the ?TuketHSD man page.
But you can easily hack together a copy that does allow you to do it. First find the code for the existing method with getAnywhere(plot.TukeyHSD). Then adapt it like so:
tuk_plot <- function (x, xlab, ylab, ylabels = NULL, ...) {
for (i in seq_along(x)) {
xi <- x[[i]][, -4L, drop = FALSE]
yvals <- nrow(xi):1L
dev.hold()
on.exit(dev.flush())
plot(c(xi[, "lwr"], xi[, "upr"]), rep.int(yvals, 2L),
type = "n", axes = FALSE, xlab = "", ylab = "", main = NULL,
...)
axis(1, ...)
# change for custom axis labels
if (is.null(ylabels)) ylabels <- dimnames(xi)[[1L]]
axis(2, at = nrow(xi):1, labels = ylabels,
srt = 0, ...)
abline(h = yvals, lty = 1, lwd = 0.5, col = "lightgray")
abline(v = 0, lty = 2, lwd = 0.5, ...)
segments(xi[, "lwr"], yvals, xi[, "upr"], yvals, ...)
segments(as.vector(xi), rep.int(yvals - 0.1, 3L), as.vector(xi),
rep.int(yvals + 0.1, 3L), ...)
title(main = paste0(format(100 * attr(x, "conf.level"),
digits = 2L), "% family-wise confidence level\n"),
# change for custom axis titles
xlab = xlab, ylab = ylab)
box()
dev.flush()
on.exit()
}
}
Now you can adjust the x and y axis along with custom y-labels:
tuk_plot(tuk, "Hello X Axis", "Hello Y Axis", c("One", "Two", "Three"))
If you don't provide the y-labels the default ones from the model will show up.
Reproducible Example:
fm1 <- aov(breaks ~ wool + tension, data = warpbreaks))
tuk <- TukeyHSD(fm1, "tension")
Related
I am using R in order to create a graph for my Tukey Test after my ANOVA analysis. This is the code:
TukeyHSD(my.anova)
Tukeytest <- TukeyHSD(my.anova)
plot(Tukeytest)
I get this figure:
What I want to do is to highlight significant results (lines 1 and 3) with red color. I'd appreciate if I can get help here.
I've hacked stats:::plot.TukeyHSD to do this.
fm1 <- aov(breaks ~ wool + tension, data = warpbreaks)
tt <- TukeyHSD(fm1, "tension", ordered = TRUE)
png("tukey_red.png")
my_plot(tt)
dev.off()
There is one extra argument, and three modified lines of code (indicated by comments).
## add sig.col as an argument
my_plot <- function (x, sig.col = "red", ...) {
for (i in seq_along(x)) {
xi <- x[[i]][, -4L, drop = FALSE]
## assign colors for significant entries
seg.col <- ifelse(sign(xi[, "lwr"]*xi[, "upr"]) > 0,
sig.col, par("fg"))
yvals <- nrow(xi):1L
dev.hold()
on.exit(dev.flush())
plot(c(xi[, "lwr"], xi[, "upr"]), rep.int(yvals, 2L),
type = "n", axes = FALSE, xlab = "", ylab = "", main = NULL,
...)
axis(1, ...)
axis(2, at = nrow(xi):1, labels = dimnames(xi)[[1L]],
srt = 0, ...)
abline(h = yvals, lty = 1, lwd = 0.5, col = "lightgray")
abline(v = 0, lty = 2, lwd = 0.5, ...)
## add seg.col to the next two statements
segments(xi[, "lwr"], yvals, xi[, "upr"], yvals,
col = seg.col, ...)
segments(as.vector(xi), rep.int(yvals - 0.1, 3L), as.vector(xi),
rep.int(yvals + 0.1, 3L),
rep(seg.col, 3), ...)
title(main = paste0(format(100 * attr(x, "conf.level"),
digits = 2L), "% family-wise confidence level\n"),
xlab = paste("Differences in mean levels of", names(x)[i]))
box()
dev.flush()
on.exit()
}
}
I'm a beginner in coding. I was trying to create an interaction plot. Here's my code:
data is clinicaltrials from the data of the book "Learning Statistics with R."
library(sciplot)
library(lsr)
library(gplots)
lineplot.CI(x.factor = clin.trial$drug,
response = clin.trial$mood.gain,
group = clin.trial$therapy,
ci.fun = ciMean,
xlab = "Drug",
ylab = "Mood Gain")
and it produces the graph like this:
As can be seen in the graph, the legend box is not within my screen.
Also I tried creating another plot using the following code:
interaction.plot(x.factor = clin.trial$drug,
trace.factor = clin.trial$therapy,
response = clin.trial$mood.gain,
fun = mean,
type = "l",
lty = 1, # line type
lwd = 2, # line width
legend = T,
xlab = "Drug", ylab = "Mood Gain",
col = c("#00AFBB", "#E7B800"),
xpd = F,
trace.label = "Therapy")
For this code, I got the graph like this:
In this graph, the legend does not have labels.
Could anyone help me with these problems regarding legend?
You probably plan to save the plot via RStudio GUI. When you resize the plot window with your mouse, you need to run the code again to refresh the legend dimensions.
However, it's advantageous to use a more sophisticated method, e.g. to save it as a png with fixed dimensions like so:
library("sciplot")
library("lsr")
library("gplots")
png("Plot_1.png", height=400, width=500)
lineplot.CI(x.factor=clin.trial$drug,
response=clin.trial$mood.gain,
group=clin.trial$therapy,
ci.fun=ciMean,
xlab="Drug",
ylab="Mood Gain"
)
dev.off()
png("Plot_2.png", height=400, width=500)
interaction.plot(x.factor=clin.trial$drug,
trace.factor=clin.trial$therapy,
response=clin.trial$mood.gain,
fun=mean,
type="l",
lty=1, # line type
lwd=2, # line width
legend=T,
xlab="Drug", ylab="Mood Gain",
col=c("#00AFBB", "#E7B800"),
xpd=F,
trace.label="Therapy")
dev.off()
The plots are saved into your working directory, check getwd() .
Edit
You could also adjust the legend position.
In lineplot.CI you may use arguments; either by using characters just for x, e.g. x.leg="topleft" or both coordinates as numeric x.leg=.8, y.leg=2.2.
interaction.plot does not provide yet this functionality. I provide a hacked version below. Arguments are called xleg and yleg, functionality as above.
See ?legend for further explanations.
interaction.plot <- function (x.factor, trace.factor, response, fun = mean,
type = c("l", "p", "b", "o", "c"), legend = TRUE,
trace.label = deparse(substitute(trace.factor)),
fixed = FALSE, xlab = deparse(substitute(x.factor)),
ylab = ylabel, ylim = range(cells, na.rm = TRUE),
lty = nc:1, col = 1, pch = c(1L:9, 0, letters),
xpd = NULL, leg.bg = par("bg"), leg.bty = "n",
xtick = FALSE, xaxt = par("xaxt"), axes = TRUE,
xleg=NULL, yleg=NULL, ...) {
ylabel <- paste(deparse(substitute(fun)), "of ", deparse(substitute(response)))
type <- match.arg(type)
cells <- tapply(response, list(x.factor, trace.factor), fun)
nr <- nrow(cells)
nc <- ncol(cells)
xvals <- 1L:nr
if (is.ordered(x.factor)) {
wn <- getOption("warn")
options(warn = -1)
xnm <- as.numeric(levels(x.factor))
options(warn = wn)
if (!anyNA(xnm))
xvals <- xnm
}
xlabs <- rownames(cells)
ylabs <- colnames(cells)
nch <- max(sapply(ylabs, nchar, type = "width"))
if (is.null(xlabs))
xlabs <- as.character(xvals)
if (is.null(ylabs))
ylabs <- as.character(1L:nc)
xlim <- range(xvals)
if (is.null(xleg)) {
xleg <- xlim[2L] + 0.05 * diff(xlim)
xlim <- xlim + c(-0.2/nr, if (legend) 0.2 + 0.02 * nch else 0.2/nr) *
diff(xlim)
}
dev.hold()
on.exit(dev.flush())
matplot(xvals, cells, ..., type = type, xlim = xlim, ylim = ylim,
xlab = xlab, ylab = ylab, axes = axes, xaxt = "n",
col = col, lty = lty, pch = pch)
if (axes && xaxt != "n") {
axisInt <- function(x, main, sub, lwd, bg, log, asp,
...) axis(1, x, ...)
mgp. <- par("mgp")
if (!xtick)
mgp.[2L] <- 0
axisInt(1, at = xvals, labels = xlabs, tick = xtick,
mgp = mgp., xaxt = xaxt, ...)
}
if (legend) {
yrng <- diff(ylim)
if (is.null(yleg))
yleg <- ylim[2L] - 0.1 * yrng
if (!is.null(xpd) || {
xpd. <- par("xpd")
!is.na(xpd.) && !xpd. && (xpd <- TRUE)
}) {
op <- par(xpd = xpd)
on.exit(par(op), add = TRUE)
}
# text(xleg, ylim[2L] - 0.05 * yrng, paste(" ",
# trace.label), adj = 0)
if (!fixed) {
ord <- sort.list(cells[nr, ], decreasing = TRUE)
ylabs <- ylabs[ord]
lty <- lty[1 + (ord - 1)%%length(lty)]
col <- col[1 + (ord - 1)%%length(col)]
pch <- pch[ord]
}
legend(xleg, yleg, legend = ylabs, col = col,
title = if (trace.label == "") NULL else trace.label,
pch = if (type %in% c("p", "b"))
pch, lty = if (type %in% c("l", "b"))
lty, bty = leg.bty, bg = leg.bg)
}
invisible()
}
Data:
lk <- "https://learningstatisticswithr.com/data.zip"
tmp <- tempfile()
tmp.dir <- tempdir()
download.file(lk, tmp)
unzip(tmp, exdir=tmp.dir)
load("data/clinicaltrial.Rdata")
I am currently busy with a Vector Autoregressive Analysis in R, using the vars package. I was wondering if the following things are possible:
1) the previous solution for a better fit on the page worked properly, but now with more variables, we have more plots and the layout is screwed again. I already played with some of the win.graph() parameters, but nothing gives me a proper readable solution.
2) The plot(irf(...) function of the vars package gives a one-graph per page output. I was wondering if this is also possible for the plot(fevd() function by adding some extra (unkown to me) parameters options
3) Also, for readability, I would like to color the graphs, plot(fevd() gives an all-kinds-of-gray output, Is it possible to change those colors?
Thank you in advance
Olivier
You will have to modify the plot function for fevd to do what you want. Here's a modified plot.varfevd function that removes all calls to par(). This allows to use layout properly. The lines that have been removed have been commented out (#). I also removed the parameter that asked for confirmation in "single" plots.
plot.varfevd <-function (x, plot.type = c("multiple", "single"), names = NULL,
main = NULL, col = NULL, ylim = NULL, ylab = NULL, xlab = NULL,
legend = NULL, names.arg = NULL, nc, mar = par("mar"), oma = par("oma"),
addbars = 1, ...)
{
K <- length(x)
ynames <- names(x)
plot.type <- match.arg(plot.type)
if (is.null(names)) {
names <- ynames
}
else {
names <- as.character(names)
if (!(all(names %in% ynames))) {
warning("\nInvalid variable name(s) supplied, using first variable.\n")
names <- ynames[1]
}
}
nv <- length(names)
# op <- par(no.readonly = TRUE)
ifelse(is.null(main), main <- paste("FEVD for", names), main <- rep(main,
nv)[1:nv])
ifelse(is.null(col), col <- gray.colors(K), col <- rep(col,
K)[1:K])
ifelse(is.null(ylab), ylab <- rep("Percentage", nv), ylab <- rep(ylab,
nv)[1:nv])
ifelse(is.null(xlab), xlab <- rep("Horizon", nv), xlab <- rep(xlab,
nv)[1:nv])
ifelse(is.null(ylim), ylim <- c(0, 1), ylim <- ylim)
ifelse(is.null(legend), legend <- ynames, legend <- legend)
if (is.null(names.arg))
names.arg <- c(paste(1:nrow(x[[1]])), rep(NA, addbars))
plotfevd <- function(x, main, col, ylab, xlab, names.arg,
ylim, ...) {
addbars <- as.integer(addbars)
if (addbars > 0) {
hmat <- matrix(0, nrow = K, ncol = addbars)
xvalue <- cbind(t(x), hmat)
barplot(xvalue, main = main, col = col, ylab = ylab,
xlab = xlab, names.arg = names.arg, ylim = ylim,
legend.text = legend, ...)
abline(h = 0)
}
else {
xvalue <- t(x)
barplot(xvalue, main = main, col = col, ylab = ylab,
xlab = xlab, names.arg = names.arg, ylim = ylim,
...)
abline(h = 0)
}
}
if (plot.type == "single") {
# par(mar = mar, oma = oma)
# if (nv > 1)
# par(ask = TRUE)
for (i in 1:nv) {
plotfevd(x = x[[names[i]]], main = main[i], col = col,
ylab = ylab[i], xlab = xlab[i], names.arg = names.arg,
ylim = ylim, ...)
}
}
else if (plot.type == "multiple") {
if (missing(nc)) {
nc <- ifelse(nv > 4, 2, 1)
}
nr <- ceiling(nv/nc)
par(mfcol = c(nr, nc), mar = mar, oma = oma)
for (i in 1:nv) {
plotfevd(x = x[[names[i]]], main = main[i], col = col,
ylab = ylab[i], xlab = xlab[i], names.arg = names.arg,
ylim = ylim, ...)
}
}
# on.exit(par(op))
}
Then, you will need short variable names. Pick acronyms if needed.
library(vars)
data(Canada)
colnames(Canada) <-c("name1","name2","name3","name4")
var <- VAR(Canada , p=4 , type = "both")
Using a wide plot window (using win.graph) and using layout (to get the placement of your eight plots), you can get all charts displayed properly. I also changed the colors of the plots as requested. Finally, we are now using single plots as there are no calls to par() which do not sit well with layout().
win.graph(width=15,height=8)
layout(matrix(1:8,ncol=2))
plot.varfevd(fevd(var, n.ahead = 10 ),plot.type = "single", col=1:4)
plot.varfevd(fevd(var, n.ahead = 10 ),plot.type = "single", col=1:4)
I am trying to create a function to draw scatterplots of variables, something like the following:
plotting = function(x,y){
plot(x, y,
main= "PM10 and Electricity use",
ylab= "",
xlab= "",
col= "blue", pch = 19, cex = 1, lty = "solid", lwd = 2)
}
y = PM10
x = Total_E*population
plotting(x,y)
(Note: PM10, Total_E, population are all vectors of numbers.)
Is that possible to change xlab, ylab to the names of the variables, say ylab to "PM10", and xlab to "Total_E*population" or even "Total_E times population"?
you are looking for non-standard evaluation. This is accomplished with substitute and deparse. ...
plotting <- function(x, y) {
plot(x, y, main = "PM10 and Electricity use",
ylab = deparse(substitute(y)),
xlab = deparse(substitute(x))
)
}
I would like to do a graph in R using our company colors. This means the background of all charts should be a light blue, the plotting region however should be white. I was searching for answers and found that drawing a rect does the job (almost). However the plotting region is now white and the graph not visible anymore. Is this even possible?
getSymbols('SPY', from='1998-01-01', to='2011-07-31', adjust=T)
GRAPH_BLUE<-rgb(43/255, 71/255,153/255)
GRAPH_ORANGE<-rgb(243/255, 112/255, 33/255)
GRAPH_BACKGROUND<-rgb(180/255, 226/255, 244/255)
par(bg=GRAPH_BACKGROUND)
colorPlottingBackground<-function(PlottingBackgroundColor = "white"){
rect(par("usr")[1], par("usr")[3], par("usr")[2], par("usr")[4], col ="white")
}
plot.xts(SPY, col=GRAPH_BLUE)
colorPlottingBackground()
I know you already accepted #plannapus's answer, but this is a much simpler solution
par(bg="lightblue")
plot(0, 0, type="n", ann=FALSE, axes=FALSE)
u <- par("usr") # The coordinates of the plot area
rect(u[1], u[3], u[2], u[4], col="white", border=NA)
par(new=TRUE)
plot(1:10, cumsum(rnorm(10)))
What you basically do is to overlay two plots using par(new=TRUE): one with only a white rectangle; and another one with the contents you actually want to plot.
The issue is that you plot your white rectangle after plotting your data, therefore overwriting them. Since plot.xts doesn't have an argument add that would allow you to call it after drawing the rectangle, the only solution I see would be to modify function plot.xts.
plot.xtsMODIFIED<-function (x, y = NULL, type = "l", auto.grid = TRUE, major.ticks = "auto",
minor.ticks = TRUE, major.format = TRUE, bar.col = "grey",
candle.col = "white", ann = TRUE, axes = TRUE, ...)
{
series.title <- deparse(substitute(x))
ep <- axTicksByTime(x, major.ticks, format.labels = major.format)
otype <- type
if (is.OHLC(x) && type %in% c("candles", "bars")) {
x <- x[, has.OHLC(x, TRUE)]
xycoords <- list(x = .index(x), y = seq(min(x), max(x),
length.out = NROW(x)))
type <- "n"
}
else {
if (NCOL(x) > 1)
warning("only the univariate series will be plotted")
if (is.null(y))
xycoords <- xy.coords(.index(x), x[, 1])
}
###The next three lines are the only modifications i made to the function####
plot(xycoords$x, xycoords$y, type = "n", axes = FALSE, ann = FALSE)
rect(par("usr")[1], par("usr")[3], par("usr")[2], par("usr")[4], col ="white")
if(type=="l"){lines(xycoords$x, xycoords$y, ...)}
if (auto.grid) {
abline(v = xycoords$x[ep], col = "grey", lty = 4)
grid(NA, NULL)
}
if (is.OHLC(x) && otype == "candles")
plot.ohlc.candles(x, bar.col = bar.col, candle.col = candle.col,
...)
dots <- list(...)
if (axes) {
if (minor.ticks)
axis(1, at = xycoords$x, labels = FALSE, col = "#BBBBBB",
...)
axis(1, at = xycoords$x[ep], labels = names(ep), las = 1,
lwd = 1, mgp = c(3, 2, 0), ...)
axis(2, ...)
}
box()
if (!"main" %in% names(dots))
title(main = series.title)
do.call("title", list(...))
assign(".plot.xts", recordPlot(), .GlobalEnv)
}
Then your script become:
library(quantmod)
getSymbols('SPY', from='1998-01-01', to='2011-07-31', adjust=T)
GRAPH_BLUE<-rgb(43/255, 71/255,153/255)
GRAPH_BACKGROUND<-rgb(180/255, 226/255, 244/255)
par(bg=GRAPH_BACKGROUND)
plot.xtsMODIFIED(SPY, col=GRAPH_BLUE)
The error you're getting (Error in axis(1, at = xycoords$x, labels = FALSE, col = "#BBBBBB", ...) : formal argument "col" matched by multiple actual arguments.) was also thrown with your previous script. It has to do with the fact that plot.xts uses several time argument ... and that argument col is both valid for axis and plot(or here in my modified version, lines). If you want to avoid it, i see two solutions:
Either you want your axis to be of the same color as your line and therefore you have to change the line that says:
...
axis(1, at = xycoords$x, labels = FALSE, col = "#BBBBBB",
...)
...
Into
...
axis(1, at = xycoords$x, labels = FALSE, ...)
...
Or you want the axis to have the color intended by the writer of the original plot.xts in which case you need to differenciate the color of the lines and that of the axis.
plot.xtsMODIFIED<-function (x, y = NULL, type = "l", auto.grid = TRUE, major.ticks = "auto",
minor.ticks = TRUE, major.format = TRUE, bar.col = "grey",
candle.col = "white", ann = TRUE, axes = TRUE,
lcol, ...)
{
...
if(type=="l"){lines(xycoords$x, xycoords$y, lcol, ...)}
...
}
And then in your actual call:
plot.xtsMODIFIED(SPY, lcol=GRAPH_BLUE)
plot.xts will accept the panel.first argument, which is another way to draw the rectangle before plotting the line.
library(quantmod)
getSymbols('SPY', from='1998-01-01', to='2011-07-31', adjust=T)
GRAPH_BLUE<-rgb(43/255, 71/255,153/255)
GRAPH_BACKGROUND<-rgb(180/255, 226/255, 244/255)
par(bg=GRAPH_BACKGROUND)
white.rect=function() do.call(rect,as.list(c(par()$usr[c(1,3,2,4)],col="white")))
plot.xts(SPY,panel.first=white.rect())
This does not address the issue with col=GRAPH_BLUE pointed out by #plannapus.