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