Related
I have a 2 x 2 figure where the columns represent two different variables and the rows represent two different locations. How can I add the names of the two locations to the two rows?
Example Data
library(biwavelet)
par(mfrow = c(2,2),
oma = c(3,3,0,0) + 0.1,
mar = c(1,1,1,1) + 0.1)
dat <- as.data.frame(matrix(nrow = 500, ncol = 2))
dat[1] <- seq(1,500)
dat[2] <- sin(dat[1])
# top-left figure
plot(wt(dat),
xaxt = 'n',
xlab = "",
cex.axis = 1.5,
cex.lab = 1.5)
axis(1, at = seq(0, 500, by = 100), cex.axis = 0.1, col.axis = 'NA')
title("Variable 1", line = 0.1, cex.main = 1.5)
# top-right figure
dat[2] <- sin(dat[1]*.5)
plot(wt(dat),
xaxt = 'n',
col.axis = 'NA',
xlab = "",
ylab = "")
axis(1, at = seq(0, 500, by = 100), cex.axis = 0.1, col.axis = 'NA')
title("Variable 2", line = 0.1, cex.main = 1.5)
# bottom-left figure
dat[2] <- sin(dat[1]*.25)
plot(wt(dat),
cex.axis = 1.5)
# bottom-right figure
dat[2] <- sin(dat[1]*.125)
plot(wt(dat),
col.axis = 'NA',
ylab = "",
xlab = "")
axis(1, at = seq(0, 500, by = 100), cex.axis = 1.5)
title(xlab = "Time (hours)",
ylab = "Period",
outer = TRUE,
line = 1.5,
cex.lab = 1.5)
The ideal figure would look like this
Neither of the suggested solutions so far have put the right-hand labels in the orientation requested. You cannot do so with mtext, but rather need to use text, first allowing text to display outside the plot region with par(xpd=NA). (See ?text and ?par, where one reads that the srt,rotation, parameter only applies to text):
par(mfrow=c(2,2), xpd=FALSE)
par(mar = c(1,1,1,1) + 2)
plot(disp ~ mpg, data = mtcars)
mtext("disp 1", side=3)
plot(I(2*disp) ~ mpg, data = mtcars)
mtext("disp 2", side=3); par(xpd=NA)
text("mpg 1", x=36, y=500, srt=270)
plot(disp ~ I(2*mpg), data = mtcars); par(xpd=NA)
plot(I(2*disp) ~ I(2*mpg), data = mtcars)
text("mpg 2", x=72, y=500, srt=270)
It is not as automatic as mtext in the sense that one needs to look at each plotting figure separately to derive a estimate for the x and y positions in the plotting coordinates.
Here's one method:
par(mfrow=c(2,2))
par(mar = c(1,1,1,1) + 0.1)
plot(disp ~ mpg, data = mtcars)
mtext("disp 1", side=3)
plot(I(2*disp) ~ mpg, data = mtcars)
mtext("disp 2", side=3)
mtext("mpg 1", side=4)
plot(disp ~ I(2*mpg), data = mtcars)
plot(I(2*disp) ~ I(2*mpg), data = mtcars)
mtext("mpg 2", side=4)
Unfortunately, mtext does not support rotating text, so you're stuck with the right labels being oriented as they are.
In case anyone stumbles across this page, the code I ended up using was based on #IRTFM answer, see below. It was challenging finding the appropriate y = in the text() function. I used an iterative approach and found the y = to be much lower than I anticipated.
library(biwavelet)
par(mfrow = c(2,2), xpd=F)
par(mar = c(1,1,1.1,1.1) + 0.1,
oma = c(3,3,0.5,0.5) + 0.1)
dat <- as.data.frame(matrix(nrow = 500, ncol = 2))
dat[1] <- seq(1,500)
dat[2] <- sin(dat[1])
# top-left figure
plot(wt(dat),
xaxt = 'n',
xlab = "",
cex.axis = 1.5,
cex.lab = 1.5)
axis(1, at = seq(0, 500, by = 100), cex.axis = 1.5, col.axis = 'NA')
mtext("Variable 1", side = 3, cex = 1.5, line = 0.1)
box(lty = "solid", col = 'black')
# top-right figure
dat[2] <- sin(dat[1]*.5)
plot(wt(dat),
xaxt = 'n',
col.axis = 'NA',
xlab = "",
ylab = "")
axis(1, at = seq(100, 500, by = 100), cex.axis = 0.1, col.axis = 'NA')
mtext("Variable 2", side = 3, cex = 1.5, line = 0.1)
text("Location 1", x = 520, y = 4.1, srt = 270, cex = 1.5, xpd=NA)
box(lty = "solid", col = 'black')
# bottom-left figure
dat[2] <- sin(dat[1]*.25)
plot(wt(dat),
cex.axis = 1.5,
xlab = "",
ylab = "")
axis(1, at = seq(100, 500, by = 100), cex.axis = 1.5)
box(lty = "solid", col = 'black')
# bottom-right figure
dat[2] <- sin(dat[1]*.125)
plot(wt(dat),
col.axis = 'NA',
ylab = "",
xlab = "")
axis(1, at = seq(100, 500, by = 100), cex.axis = 1.5)
text("Location 2", x = 520, y = 4.5, srt = 270, cex = 1.5, xpd=NA)
box(lty = "solid", col = 'black')
title(xlab = "Time (hours)",
ylab = "Period",
outer = TRUE,
line = 1.5,
cex.lab = 1.5)
I can plot the barplot in Excel with decimal points in y-axis limits as shown below.
But I would not be able to change the y-axis limits in R.
Here is my code in R.
par(mfrow=c(1, 1), mar=c(7, 4, 5, 6))
mydata <- data.frame(Algorithm1=c(95.85, 96.94), Algorithm2=c(96.04, 96.84), Algorithm3=c(95, 95.30))
barplot(as.matrix(mydata), main="Precision", ylim=range(0:100),
beside=T, col=c("red", "blue"), las=1, border = 0, cex.lab=1, cex.axis=1, font=1,col.axis="black", ylab = "Percentage",
legend.text = c("X1", "X2"),
args.legend = list(x ='topright', bty='n', inset=c(-0.20,0)))
Thanks in advance for your answer.
You can also use ggplot2 and scales.
library(dplyr)
library(ggplot2)
library(scales)
mydata <- data.frame(Algorithm = rep(c('Algorithm1','Algorithm2','Algorithm3'), each=2),
variable_x = rep(c('X1','X2'),3),
values=c(0.9585, 0.9694,0.9604, 0.9684, 0.95, 0.9530))
mydata %>%
ggplot(aes(x=Algorithm,y=values,fill=variable_x))+
geom_bar(stat='identity', position='dodge')+
scale_y_continuous(labels = scales::percent, limits = c(0.94,0.975), oob = rescale_none)+
scale_fill_manual(values= c(X1='red',X2='blue'))
Set the limit of y and xpd = FALSE.
FALSE : all plotting is clipped to the plot region
TRUE : all plotting is clipped to the figure region
NA : all plotting is clipped to the device region
library(RColorBrewer)
color <- brewer.pal(3, "Set1")[2:1]
plot.new()
plot.window(xlim = c(0, 10), ylim = c(94, 97.5), yaxs = "i")
abline(h = seq(94, 97.5, 0.5), col = 8)
barplot(as.matrix(mydata), beside = T, col = color,
border = NA, legend.text = c("X1", "X2"),
args.legend = list(x = 'topright', bty = "n"), xpd = F, add = T)
You could do:
tickPoints <- 20 * (0:5)
par(mfrow = c(1, 1), mar = c(7, 4, 5, 6))
mydata <- data.frame(
Algorithm1 = c(95.85, 96.94),
Algorithm2 = c(96.04, 96.84),
Algorithm3 = c(95, 95.30)
)
barplot(
as.matrix(mydata), main = "Precision", beside = T, col = c("red", "blue"),
las = 1, border = 0, cex.lab = 1, cex.axis = 1, font = 1, col.axis = "black",
ylab = "Percentage", legend.text = c("X1", "X2"),
args.legend = list(x = 'topright', bty = 'n',inset = c(-0.20, 0)),
axes = FALSE,
ylim = range(tickPoints)
)
axis(side = 2, at = tickPoints, labels = sprintf("%0.1f", tickPoints))
Note the axes = FALSE in the call to barplot
I have found multiple ways to create a secondary y-axis in plot but I couldn't find a way to create a secondary y-axis in histogram.
Here is a sample code:
a <- sample(90:110, 50, replace=TRUE)
b <- runif(50, min=0, max=1)
hist(a)
lines(b)
b is too small to show in hist(a) so is there any way that I can see both in the histogram?
Technically a solution may be quite an identical to the approach proposed for the plots in this answer. The idea is to use overlapping of two plots as proposed by #r2evans.
It makes sense to use color coding:
# set color rules
col_a <- "red"
col_b <- "darkblue"
col_common <- "black"
Then let's draw the histogram and the plot:
# draw a histogram first
par(mar = c(5, 5, 5, 5) + 0.3)
hist(a, col = col_a, axes = FALSE, xlab = "", ylab = "", main = "")
# add both axes with the labels
axis(side = 1, xlim = seq(along.with = b), col = col_a, col.axis = col_a)
mtext(side = 1, text = "a_value", col = col_a, line = 2.5)
axis(side = 2, col = col_a, col.axis = col_a, ylab = "")
mtext(side = 2, text = "a_Frequency", col = col_a, line = 2.5)
# ... and add an overlaying plot
par(new=TRUE)
plot(b, ylim = c(0, 1), axes = FALSE, col = col_b, type = "l", xlab = "", ylab = "")
points(b, col = col_b, pch = 20, xlab = "", ylab = "")
axis(side = 3, xlim = seq(along.with = b), col = col_b, col.axis = col_b)
mtext(side = 3, text = "b_index", col = col_b, line = 2.5)
axis(side = 4, ylim = c(0, 1), col = col_b, col.axis = col_b)
mtext(side = 4, text = "b_value", col = col_b, line = 2.5)
box(col = col_common)
In R, is there a way to add means to a plot at specific x-axis. For example, I want to do something like:
plot(1, 1, xlim = c(0, 6.5), ylim = c(0,300), type = 'n', xlab = '', ylab = '', xaxt = 'n') #xaxs="i",yaxs="i")
boxplot(dataset,at = 0.5, add = T, range = 6,yaxt = 'n')
points(mean(dataset), at = 0.5, add = T)
I get a message saying "at" and "add" are 'not a graphical parameter'. Is there a workaround?
So I am using RStudio. There are six different values (data_a, data_b, data_c, data_d, data_e, and data_f) each with 11 numbers. My current code looks like follows:
par(xpd = FALSE)
par(mar=c(8,4.5,2,1))
plot(1, 1, xlim = c(0, 6.5), ylim = c(0,300), type = 'n', xlab = '', ylab = '', xaxt = 'n') #xaxs="i",yaxs="i")
boxplot(data_a,at = 0.5, add = T, range = 6,yaxt = 'n')
boxplot(data_b,at = 1.5, add = T, range = 6,yaxt = 'n')
boxplot(data_c,at = 2.5, add = T, range = 6,yaxt = 'n')
boxplot(data_d,at = 4, add = T, range = 6,yaxt = 'n')
boxplot(data_e,at = 5, add = T, range = 6,yaxt = 'n')
boxplot(data_f,at = 6, add = T, range = 6,yaxt = 'n')
axis(2, at = 150, pos = -0.65, tck = 0, labels = 'X axis label',cex.axis=1.1)
axis(1, at = c(0.5,1.5,2.5,4,5,6),labels=c('','','','','',''))
axis(1, at = c(1.5,5),pos= -25,labels=c('label 1','labe 2'),tick=FALSE)
axis(1, at = c(3.25),labels=c(''),tck=-0.15)
axis(1, at = c(3.25),pos = -50,labels=c('Y axis label'),tick=FALSE)
abline(v=3.25)
par(xpd = NA)
text(0.5,-30, expression("a))
text(1.5,-30, expression("b"))
text(2.5,-30,"c")
text(4,-30, expression(d))
text(5,-30, expression("e"))
text(6,-30,"f")
Now I want to be able to add mean.
You can try this to get the desired plot (with randomly generated data_a, data_b etc.):
par(xpd = FALSE)
par(mar=c(8,4.5,2,1))
plot(1, 1, xlim = c(0, 6.5), ylim = c(0,300), type = 'n', xlab = '', ylab = '', xaxt = 'n') #xaxs="i",yaxs="i")
data_a <- runif(11, 0, 300)
data_b <- runif(11, 0, 300)
data_c <- runif(11, 0, 300)
data_d <- runif(11, 0, 300)
data_e <- runif(11, 0, 300)
data_f <- runif(11, 0, 300)
boxplot(data_a,at = 0.5, add = T, range = 6,yaxt = 'n')
boxplot(data_b,at = 1.5, add = T, range = 6,yaxt = 'n')
boxplot(data_c,at = 2.5, add = T, range = 6,yaxt = 'n')
boxplot(data_d,at = 4, add = T, range = 6,yaxt = 'n')
boxplot(data_e,at = 5, add = T, range = 6,yaxt = 'n')
boxplot(data_f,at = 6, add = T, range = 6,yaxt = 'n')
axis(2, at = 150, pos = -0.65, tck = 0, labels = 'X axis label',cex.axis=1.1)
axis(1, at = c(0.5,1.5,2.5,4,5,6),labels=c('','','','','',''))
axis(1, at = c(1.5,5),pos= -25,labels=c('label 1','label 2'),tick=FALSE)
axis(1, at = c(3.25),labels=c(''),tck=-0.15)
axis(1, at = c(3.25),pos = -50,labels=c('Y axis label'),tick=FALSE)
abline(v=3.25)
par(xpd = NA)
text(0.5,-30, expression("a"))
text(1.5,-30, expression("b"))
text(2.5,-30,"c")
text(4,-30, expression("d"))
text(5,-30, expression("e"))
text(6,-30,"f")
points(c(0.5,1.5,2.5,4,5,6), c(mean(data_a), mean(data_b), mean(data_c), mean(data_d), mean(data_e), mean(data_f)), pch = 22, col = "darkgrey", lwd = 7)
With boxplots, the location of the plots on the x axis are at the units (1, 2, 3, etc.). You can check this using the function locator().
Here is an example to add means as a red circle to a boxplot using the iris dataset:
boxplot(Sepal.Length ~ Species, data = iris)
points(seq_along(levels(iris$Species)), with(iris, tapply(Sepal.Length, Species, mean)), col = "red")
I want to have my titles be above my points in a pdf plot. It seems R thinks my title is wider than my plot area even though I have my right and left plot margins set to zero.
x <- seq(from = 0.1, to = 0.9, by = 0.1)
xtitle <- c("0.1","0.2","0.3","0.4","0.5","0.6","0.7","0.8","0.9")
pdf("testpdfopts.pdf", width = 16)
par(mar = c(0, 0, 1, 0)) # only need margin at top for title
plot(
x,
rep(0.9,length(x)),
xlim = c(0, 1),
ylim = c(0, 1),
cex = 1,
xaxt = "n",
yaxt = "n",
xlab = "",
ylab = ""
)
for (i in 1:length(x)) {
title(xtitle[i],adj=x[i],cex.main=1)
}
dev.off()
Thanks in advance for any assistance
I am sort of confused with what you are trying to do. Maybe I should put my comment into complete code:
x <- seq(from = 0.1, to = 0.9, by = 0.1)
plot(
x,
rep(0.9,length(x)),
xlim = c(0, 1),
ylim = c(0, 1),
cex = 1,
xaxt = "n",
yaxt = "n",
xlab = "",
ylab = ""
)
axis(3, at = 1:9/10)
Is this equivalent to what you aim to achieve?
You can get character labels too:
x <- seq(from = 0.1, to = 0.9, by = 0.1)
plot(
x,
rep(0.9,length(x)),
xlim = c(0, 1),
ylim = c(0, 1),
cex = 1,
xaxt = "n",
yaxt = "n",
xlab = "",
ylab = ""
)
axis(3, at = 1:9/10, labels = letters[1:9])