Plotting in R with two y-axes - r

So i have a dataframe that looks like this:
I am trying to plot this so that the 'cancers' are on the x axis and then the 'oddsRatio' and 'foldIncrease' are both y-axis parameters. Ideally I have a bar graph with oddsRatio and foldIncrease for each cancer next to each other, and being distinguished by color.
This is the closest I can get:
Using the following code:
cancers = c("All Cancers", "SCLC", "Lu SCC", "Lung AC", "Larynx", "Pharynx Oral", "Cavity", "Esophageal SCC", "Esophageal AC", "Bladder", "Liver", "Cervix", "Kidney", "Pancreas")
oddsRatio = c(1, 111.3, 103.5, 21.9, 13.2, 6.6, 4.2, 3.9, 3.9, 3.8, 2.9, 1.8, 1.7, 1.6)
foldIncrease = c(1.15464695360441, 0.858680717668245, 1.29986125563649, 4.56755645705811, 2.52922152922153, 0.818596228001855, 0.892133516869108, 1.04842410881178, 1.01791768793961, 1.1423932173087, 1.1871100629828, 0.857694671793762, 1.39573948596081, 1.33458517681876)
cancerData = data.frame(cancers, oddsRatio, foldIncrease)
par(mar = c(5,5,2,5))
with(cancerData, plot(cancers, oddsRatio, type="scatter", col="red3",
ylab='Odds Ratio',
ylim=c(0,150)))
par(new = T)
with(cancerData, plot(cancers, foldIncrease, pch=16, axes=F, xlab=NA, ylab=NA, cex=1.2))
axis(side = 4)
mtext(side = 4, line = 3, 'Fold Increase')
To clarify I am looking for this:

Is this what you are wanting? (note, I used ggplot2 rather than base)
library(tidyverse)
tidy <- cancerData %>%
gather(stats, val, -cancers)
ggplot(tidy, aes(cancers, val)) +
geom_bar(aes(fill = stats), stat = "identity", position = "dodge")
Edit
Okay, so generally I don't think this is a great idea. See here for why. But if you really want to, the below should do it for you.
vars <- length(unique(cancerData$cancer))
par(mar = c(4, 4, 4, 6))
plot(1:vars, seq(0, 120, length = vars),
type = "n",
main = "Odds Ratios and Fold Increase",
bty = "n",
xaxt = "n",
xlab = "Cancers",
ylab = "Odds Ratios")
rect(1:vars - 0.25, 0, 1:vars, cancerData$oddsRatio, col = "blue")
axis(1, at = 1:vars, labels = unique(cancerData$cancer))
par(new = TRUE)
plot(1:vars, seq(0, 5, length = vars),
type = "n",
xaxt = "n",
yaxt = "n",
bty = "n",
xlab = "",
ylab = "")
rect(1:vars, 0, 1:vars + 0.25, cancerData$foldIncrease, col = "red")
axis(4)
mtext("Fold Increase", side = 4, line = 3)
legend("topright",
fill = c("blue", "red"),
legend = c("Odds Ratio", "Fold Increase"),
box.lwd = 0)

Related

base R: How to add row titles to a 2 x 2 figure

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)

R: How to combine a normal boxplot with a grouped boxplot

I'm trying to add a grouped boxplot into a boxplot with only one group. I already made it, but the problem is that I can't give a name to the boxplot that has only one group. It is simply not shown. The arguments "name" and "names" don't seem to work when your boxplot does not have different groups.
boxplot(Daten$NV,
boxwex = 0.6, at = 1:1 - 0.2,col = "yellow",
name = "Gesamtstichprobe",
main = "Guinea Pigs' Tooth Growth",
xlab = "Vitamin C dose mg",
ylab = "tooth length",
xlim = c(0.5, 3.5), ylim = c(0, 7), yaxs = "i")
boxplot(Daten$NV ~ Daten$CVKGruppe, add = TRUE,
boxwex = 0.3, at = 1:3 + 0.3, col = "orange")
You could do:
boxplot( Daten$NV,
boxwex = 0.6, at = 1:1 - 0.2, col = "yellow",
name = "Gesamtstichprobe",
main = "Guinea Pigs' Tooth Growth",
xlab = "Vitamin C dose mg",
ylab = "tooth length",
xlim = c(0.5, 3.5), ylim = c(0, 7), yaxs = "i", xaxt = "n")
axis(1, at = 0.8, labels = "Total")
boxplot(Daten$NV ~ Daten$CVKGruppe, add = TRUE,
boxwex = 0.3, at = 1:3 + 0.3, col = "orange")
Created on 2022-04-26 by the reprex package (v2.0.1)
Data
set.seed(1)
Daten <- data.frame(NV = rnorm(150, 4, 1),
CVKGruppe = rep(c("Kamera aus", "Kamera ein_VH an", "Kamera eien_VH aus"),
each = 50))

R - Plot with two y axis, bars and points not aligned

For a customer I'm trying to do a combined barplot and lineplot (with points) with two y axis.
Problem: My bars and points are not aligned.
Background: We have several machines and are measuring their number of on/of switches and the amount of time that each machine is running. We want both information together in one plot to save space, because we have several machines.
The data is aggregated by day or hour. Here's some sample data:
date <- seq(as.Date("2016-10-01"), as.Date("2016-10-10"), "day")
counts <- c(390, 377, 444, NA, NA, NA, NA, 162, 166, 145)
runtime <- c(56.8, 59.4, 51.0, NA, NA, NA, NA, 38.5, 40.9, 43.4)
df <- data.frame(date = date, counts = counts, runtime = runtime)
Here's what I tried so far:
par(mar = c(3,4,4,4) + 0.3)
barplot(df$runtime, col = "palegreen2", border = "NA", ylab = "runtime in [%]",
ylim = c(0,100), font.lab = 2)
par(new = TRUE)
ymax <- max(df$counts, na.rm = TRUE) * 1.05
plot(df$date, df$counts, type = "n", xlab = "", ylab = "", yaxt = "n",
main = "Machine 1", ylim = c(0, ymax))
abline(v = date, col = "red", lwd = 2.5)
lines(df$date, df$counts, col = "blue", lwd = 2)
points(df$date, df$counts, pch = 19, cex = 1.5)
axis(4)
mtext("Number of switching operations", side = 4, line = 3, font = 2)
I found some inspiration for two axis here: http://robjhyndman.com/hyndsight/r-graph-with-two-y-axes/
What can I do to get bars with their middle aligned with the points of the lineplot?
The problem you are running into is the call to the second plot function after the barplot. This is shifting/resizing the plotting canvas which is causing the shift in the subsequent points.
Here is a quick work-around that just rescales the points and lines onto the barplot. It saves the barplot as an object, which stores x-axis locations for the mid-points of the bars. Then, when you plot the abline, lines and points using 'bp' as the x-axis variable, they will be correctly aligned.
ymax <- max(df$counts, na.rm = TRUE) * 1.05
par(mar=c(4.1,5.1,2.1,5.1))
bp <- barplot(df$runtime, col = "palegreen2", border = "NA", ylab = "runtime in [%]",
ylim = c(0,100), font.lab = 2, xlim=c(0.2,12), )
barplot(df$runtime, col = "palegreen2", ylab = "runtime in [%]", border="NA",
ylim = c(0,100), font.lab = 2)
abline(v = bp, col = "red", lwd = 2.5)
lines(bp, df$counts/ymax*100, col = "blue", lwd = 2)
points(bp, df$counts/ymax*100, pch = 19, cex = 1.5)
axis(4,at=c(0,20,40,60,80,100), labels=c("0","100","200","300","400","500"))
mtext("Number of switching operations", side = 4, line = 3, font = 2)
axis(1, at=bp, labels=df$date)
#emilliman: Thank you for your patience and input! Your plot is not completely correct, because the scaling of the second y-axis does not fit the points' values, but your idea helped me to find a solution!
Here's my new code:
library(plyr)
ymax <- max(df$counts, na.rm = TRUE)
ymax_up <- round_any(ymax, 100, f = ceiling)
ylab <- ymax_up/5 * c(0:5)
par(mar = c(3,4,4,4) + 0.3)
bp <- barplot(df$runtime, col = "palegreen2", border = "NA", ylab = "runtime in [%]",
ylim = c(0,100), font.lab = 2, main = "Machine 1")
abline(v = bp, col = "red", lwd = 2.5)
lines(bp, 100/ymax_up * df$counts, col = "blue", lwd = 2)
points(bp, 100/ymax_up * df$counts, pch = 19, cex = 1.5)
axis(4,at=c(0,20,40,60,80,100), labels= as.character(ylab))
mtext("Number of switching operations", side = 4, line = 3, font = 2)
xlab <- as.character(df$date, format = "%b %d")
axis(1, at=bp, labels = xlab)
abline(h = c(0,100))
(http://i.imgur.com/9YtYGSD.png)
Maybe this is helpful for others who run into this problem.

R: Need y label to be two lines

I have a y label which is supposed to say
"Abundance of A. stutchburyi
(# individuals / 0.50m^2)" where # individuals.... is supposed to be the second line
The problem is, I can't make it work since I'm mixing different fonts (normal and italics). Usually I use \n but that does not work within an expression..
Here is my code, which only gives me the y label on one line:
tsaplot <- barplot(tsa$No, beside = TRUE,
xlab = "Size groups (mm)",
ylab = expression(atop(paste("Abundance of",italic("A. stutchburyi"),"(# individuals / 0.50m^2)"))),
cex.axis = 1.4, density = 50, font.lab = 2, font.axis = 2, cex.lab = .9, col = "black",
names.arg = c("0-2.0","2.1-4.0","4.1-6.0","6.1-8.0","8.1-10.0","10.1-12.0","12.1-14.0","14.1-16.0","16.1-18.0","18.1-20.0",">20.1"),
ylim = c(0,100), xpd = FALSE)
Probably a misplacement of bracket:
tl <- bquote(atop(paste("Abundance of ",italic("A. stutchburyi")),"(# individuals / 0.50"*m^2 ~ ")"))
par(mar = c(5.1, 6.1, 4.1, 2.1))
plot(1, 1, t = "n", ylab = tl)
text(1, 1, tl)
With barplot:
par(mar = c(5.1, 6.1, 4.1, 2.1))
barplot(VADeaths, ylab = tl)

R Plot - Y Axis and plotted values are not correlated

I am somewhat new to R and I am trying to plot the following:
x <- c(1:13)
y <- c(19.77, 18.07, 20.55, 16.42, 18.47, 20.18, 22.91, 13.18, 18.07, 17.05, 13.45, 11.11, 22.52)
y2 <- c(26.93, 24.5, 25.73, 23.65, 20.50, 29.58, 18.8, 17.38, 12.2, 18.17, 12.55, 15.63, 26.07)
par(mar=c(5,7,5,3), pch=22, col="Black")
plot(x, y2, main="TITLE", xaxt = "n", xlab='', yaxt = "n", ylab = "", type="b", col="Blue")
par(new = TRUE)
plot(x, y, xaxt = "n", xlab='', yaxt = "n", ylab = "", type="b", col="cyan", pch=21)
range <- seq(0, 30, 1)
axis(1, at=x, labels=x)
axis(2, at=range, labels=range, las=1)
mtext(side = 1, text = "X", line = 3, col="Black")
mtext(side = 2, text = "Tiempo", line = 5, xpd=FALSE, col="Black")
# Legend.
legend(x= "bottomleft", y=0.92, legend=c("Exp1","Exp2"), col=c("cyan", "blue"), pch=c("_","_"))
It plots OK, as follows:
However, I feel that the y axis is not correlating to the real values. For example, in the data (y and y2) we can see that one of the maximum values is 26.93 but in the data, the highest value is around to 23 according to the plot.
I have been playing with the range variable but I still haven't found any way to correct this. Google has been of no help since I am not sure about how should I search for this problem. Does any of you have any idea of what I am doing wrong?
Also, I want the values to range from 0 to 30, not from 11 to 23. Maybe this is related to the problem.
Any tip would be valuable! Thanks in advance.
Staying as close as possible to your code, you could change lines #5 and #7 like this:
plot(y2 ~ x, main="TITLE", xaxt = "n", xlab='', yaxt = "n", ylab = "", type = "b", col = "Blue", ylim = c(0,30))
lines(y ~ x, xaxt = "n", xlab = '', yaxt = "n", ylab = "", type = "b", col = "cyan", pch = 21)
Use matplot:
matplot(x, cbind(y2,y), t='b', col = c("blue", "cyan"), pch = c(22, 21), lty = c(1,1), xaxt = "n", xlab="", yaxt = "n", ylab = "")
axis(1, at=x, labels=x)
axis(2, at=range, labels=range, las=1)
mtext(side = 1, text = "X", line = 3, col="Black")
mtext(side = 2, text = "Tiempo", line = 5, xpd=FALSE, col="Black")
legend(x= "bottomleft", y=0.92, legend=c("Exp1","Exp2"), col=c("cyan", "blue"), pch=c("_","_"))

Resources