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

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))

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)

How to plot a density function of two variables?

I have two variables with the same length, v1 = actual alpha and v2 = stimulated alpha.
v1= (0.1, 0.6, 0.8, 0.11)
v2= (0.3, 0.1, 0.5, 0.7)
I want to show a density function where these two are compared, kind replicating this picture:
To make the plotting easier, I would create a data frame like this:
v1 <- c(0.1, 0.6, 0.8, 0.11)
v2 <- c(0.3, 0.1, 0.5, 0.7)
df <- data.frame(x = c(v1, v2), group = rep(c("Actual", "Simulated"), each = 4))
Now you can plot the densities easily using ggplot:
library(ggplot2)
ggplot(df) +
stat_density(aes(x, linetype = group), geom = "line", position = "identity") +
scale_linetype_manual(values = c(1, 2)) +
theme_bw() +
theme(legend.position = c(0.9, 0.85))
Of course, this doesn't look much like the density plot you provided - that's just because the data in v1 and v2 are too short to have a central tendency. Here's exactly the same plot with some toy data that better matches the data used in your plot:
set.seed(69)
v1 <- rnorm(100, -0.1, 0.12)
v2 <- rnorm(100, 0, 0.06)
df <- data.frame(x = c(v1, v2), group = rep(c("Actual", "Simulated"), each = 100))
ggplot(df) +
stat_density(aes(x, linetype = group), geom = "line", position = "identity") +
scale_linetype_manual(values = c(1, 2)) +
theme_bw() +
theme(legend.position = c(0.9, 0.85)) +
scale_x_continuous(limits = c(-.6, .4))
Created on 2020-05-21 by the reprex package (v0.3.0)
Here's a base R solution (based on #Allan's second dataframe):
hist(df$x[df$group=="Simulated"],
freq = F,
xlab = "Alpha in %",
border = "white",
main = "Density function for Actual and Simulated data", cex.main = 0.9,
xlim = range(df$x[df$group=="Actual"]))
lines(density(df$x[df$group=="Simulated"]), lty = 2)
lines(density(df$x[df$group=="Actual"]), lty = 1)
legend("topleft", legend = c("Actual", "Simulated"), bty = "n", lty = c(1,2))
grid()
Alternatively, with a bit more color:
hist(df$x[df$group=="Simulated"],
freq = F,
xlab = "Alpha in %",
border = "white",
main = "Density function for Actual and Simulated Alpha", cex.main = 0.9,
xlim = range(df$x[df$group=="Actual"]))
bg <- par("usr")
rect(bg[1], bg[3], bg[2], bg[4], col="grey50", border = NA, density = 70)
grid()
lines(density(df$x[df$group=="Simulated"]), lty = 2, col = "blue")
lines(density(df$x[df$group=="Actual"]), lty = 1, col = "blue")
legend("topleft", legend = c("Actual", "Simulated"), bty = "n", lty = c(1,2), col = "blue")

How to change y axis limits in decimal points in R?

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

R Shiny plot won't render

Hi can anyone see what is the problem with the code below?
output$zscore_chart <- renderPlot({
xvals <- 2:186
req(input$countrySelectZScore)
idx_country = which(input$countrySelectZScore == esiCountries)
max_comp_z <- max(esiData_DF[idx_country, 2:186], na.rm = TRUE)
overall_max_z <- max(max_comp_z, na.rm = TRUE)
foo = ts(esiData_DF[idx_country, 2:186], frequency = 12, start = 2001)
dates = seq(as.Date("2001-01-01"), by = "month", along = foo)
plot(x = 2:186, y = esiData_DF[idx_country, 2:186], type = "l",
xlab = "", ylab = "", col = "grey20", ylim = c(-2, overall_max_z),
lwd=3,las=2)
mtext("Quarterly percentage changes", side = 3, adj = 0, line = 0.1,
cex = 1, font = 0.5)
axis(1, at = xvals, label = dates, cex.axis = 1, las = 2)
mtext("Economic Sentiment Indicators", side = 3, adj = 0,
line = 1.2, cex = 2, font = 2)
legend(
"bottom",
lty = c(1,1),
lwd = c(3,3),
col = c("grey20", "green2"),
legend = c("Economic Sentiment Indicator", "GDP growth"),
bty = "n",
xjust = 0.5,
yjust = 0.5,
horiz = TRUE
)
}, height = 525)
esiData_DF is the DF used to index and plot the correct data. The dataframe has the country names down the left hand side with the dates, monthly across the top. I need the plot to render but it wont when I run the app. Any ideas?
The data continues to the right, up to May 2017 monthly.

Plotting in R with two y-axes

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)

Resources