I was wondering if it is possible to seperate two plots from eachother (both should be on the same plot, using double Y axis). So the double plot should be split into two but without actually plotting them seperate - par(mfrow(1,2)).
I was trying to imitate it with layout plot, or with latticeExtra, ggplot but no success.
I have two different dataset one for the exchange rate one for the logaritmic returns.
par(mar=c(4,4,3,4))
plot(rates$EURHUF~rates$Date, type="l", ylab="Rate", main="EUR/HUF", xlab="Time")
par(new=TRUE)
plot(reteslog$EURHUF~rateslog$Date, type="l", xaxt="n", yaxt="n", ylab="", xlab="", col="red")
axis(side=4)
mtext("Log return", side=4, line=3)
legend("topleft", c("EUR/HUF Rates","EUR/HUF Logreturns"), col=c("black", "red"), lty=c(1,1))
So far I am here, I just don't know how to seperate them or scale them (maybe using margin, or layout?)
Thank you very much guys for helping
I have a solution to this that isn't too outlandish, and is entirely in base, which is nice. For it to work, you just need to be able to force all of your data onto the same scale, which usually isn't a hassle.
The idea is that once your data is on the same scale, you can plot it all normally, and then add in custom axes that show the respective scales of the different data.
set.seed(1986)
d01 <- sample(x = 1:20,
size = 200,
replace = TRUE)
d02 <- sample(x = 31:45,
size = 200,
replace = TRUE)
# pdf(file = "<some/path/to/image.pdf>",
# width = 4L,
# height = 4L) # plot to a pdf
jpeg(file = "<some/path/to/image.jpeg>") # plot to a jpeg
par(mar=c(3.5, 3.5, 2, 3.5)) # parameters to make things prettier
par(mgp=c(2.2, 1, 0)) # parameters to make things prettier
plot(x = 0,
y = 0,
type = "n",
xlim = c(1, 200),
ylim = c(1, 50),
xlab = "Label 01!",
ylab = "Label 02!",
axes = FALSE,
frame.plot = TRUE)
points(d01,
pch = 1,
col = "blue") # data 01
points(d02,
pch = 2,
col = "red") # data 02
mtext("Label 03!",
side = 4,
line = 2) # your extra y axis label
xticks <- seq(from = 0,
to = 200,
by = 50) # tick mark labels
xtickpositions <- seq(from = 0,
to = 200,
by = 50) # tick mark positions on the x axis
axis(side = 1,
at = xtickpositions,
labels = xticks,
col.axis="black",
las = 2,
lwd = 0,
lwd.ticks = 1,
tck = -0.025) # add your tick marks
y01ticks <- seq(from = 0,
to = 1,
by = 0.1) # tick mark labels
y01tickpositions <- seq(from = 0,
to = 50,
by = 5) # tick mark positions on the y01 axis
axis(side = 2,
at = y01tickpositions,
labels = y01ticks,
las = 2,
lwd = 0,
lwd.ticks = 1,
tck = -0.025) # add your tick marks
y02ticks <- seq(from = 0,
to = 50,
by = 5L) # tick mark labels
y02tickpositions <- seq(from = 0,
to = 50,
by = 5) # tick mark positions on the y02 axis
axis(side = 4,
at = y02tickpositions,
labels = y02ticks,
las = 2,
lwd = 0,
lwd.ticks = 1,
tck = -0.025) # add your tick marks
dev.off() # close plotting device
A few notes:
Sizing for this plot was originally set for a pdf, which unfortunately cannot be uploaded here, however that device call is included as commented out code above. You can always play with parameters to find out what works best for you.
It can be advantageous to plot all of your axis labels with mtext().
Including simple example data in your original post is often much more helpful than the exact data you're working with. As of me writing this, I don't really know what your data looks like because I don't have access to those objects.
Related
My example data is as follows:
df <- data.frame(study = c("Hodaie","Kerrigan","Lee","Andrade","Lim"), SR = c(0.5460, 0.2270, 0.7540, 0.6420, 0.5000), SE = c(12.30, 15.70, 12.80, 13.80, 9.00), Patients = c(5, 5, 3, 6, 4))
I want to conduct the meta-analysis with SR(single group percentage), SE (standard error that I can compute based on sample size and percentage), and patients(sample size for each study), and I hope I could get the following forest plot (I found this example in an article, and they also have one group percentage data, but I can't find which R statement or argument they used):
Could anyone tell me which R statement or argument that I could use to conduct the meta-analysis and generate the forest plot above? Thank you!
I am sure there are plenty of ways to do this using packages but it can be accomplished in base R (and there are likely more elegant solutions using base R). The way I do it is to first build a blank plot much larger than the needed graphing portion, then overlay the relevant elements on it. I find one has more control over it this way. A basic example that could get you started is below. If you are new to R (based on your name NewRUser), I suggest running it line-by-line to see how it all works. Again, this is only one way and there are likely better approaches. Good luck!
Sample Data
#### Sample Data (modified from OP)
df <- data.frame(Study = c("Hodaie","Kerrigan","Lee","Andrade","Lim"),
SR = c(0.5460, 0.2270, 0.7540, 0.6420, 0.5000),
SE = c(12.30, 15.70, 12.80, 13.80, 9.00),
Patients = c(5, 5, 3, 6, 4),
ci_lo = c(30, -8.0, 50, 37, 32),
ci_hi = c(78, 53, 100, 91, 67))
### Set up plotting elements
n.studies <- nrow(df)
yy <- n.studies:1
seqx <- seq(-100, 100, 50)
## blank plot much larger than needed
plot(range(-550, 200), range(0, n.studies), type = 'n', axes = F, xlab = '', ylab = '') #blank plot, much bigger than plotting portion needed
# Set up axes
axis(side = 1, at = seqx, labels = seqx, cex.axis = 1, mgp = c(2, 1.5, 1)) # add axis and label (bottom)
mtext(side = 1, at = 0, 'Seizure Reduction', line = 2.5, cex = 0.85, padj = 1)
axis(side = 3, at = seqx, labels = seqx, cex.axis = 1, mgp = c(2, 1.5, 1)) # add axis and label (top)
mtext(side = 3, at = 0, 'Seizure Reduction', line = 2.5, cex = 0.85, padj = -1)
## add lines and dots
segments(df[, "ci_lo"], yy, df[,"ci_hi"], yy) # add lines
points(df[,"SR"]*100, yy, pch = 19) # add points
segments(x0 = 0, y0 = max(yy), y1 = 0, lty = 3, lwd = 0.75) #vertical line # 0
### Add text information
par(xpd = TRUE)
text(x = -550, y = yy, df[,"Study"], pos = 4)
text(x = -450, y = yy, df[,"SR"]*100, pos = 4)
text(x = -350, y = yy, df[,"SE"], pos = 4)
text(x = -250, y = yy, df[,"Patients"], pos = 4)
text(x = 150, y = yy, paste0(df[,"ci_lo"], "-", df[,"ci_hi"]), pos = 4)
text(x = c(seq(-550, -250, 100), 150), y = max(yy)+0.75,
c(colnames(df)[1:4], "CI"), pos = 4, font = 2)
# Add legend
legend(x = 50, y = 0.5, c("Point estimate", "95% Confidence interval"),
pch = c(19, NA), lty = c(NA, 19), bty = "n", cex = 0.65)
I've inherited this R code that plots a simple line graph. However, it does it so that the y axis values are plotted downwards below 0 (plots it in the 4th quadrant with 0 at the top and +3600 at the bottom). I want to plot the data right-side up (1st quadrant) so the y axis data goes from 0 up to +3600 at the top like a typical grade-school plot.
I've tried ylim = rev(y) but it returns an error...
I've also tried flipping the seq() command but no luck there.
list.vlevel = numeric(9) # placeholder
plot(
rep(0, length(list.vlevel)),
seq(1, length(list.vlevel)),
type = "n",
xlim = biaslim,
axes = F,
main = paste(list.var.bias[vv], list.score.bias[vv]),
xlab = "",
ylab = ""
)
abline(h = seq(1, length(list.vlevel)),
lty = 3,
col = 8)
axis(2,
labels = list.vlevel,
at = seq(length(list.vlevel), 1, -1),
las = 1)
axis(1)
box()
legend(
x = min(biasarray.var.runhour),
y = length(list.vlevel),
legend = expname,
lty = 3,
lwd = 3,
col = expcol
)
for (exp in seq(length(expname), 1, -1)) {
lines(
biasarray.var.runhour[exp, ],
seq(length(list.vlevel), 1, -1),
col = expcol[exp],
lwd = 3,
lty = 3
)
}
abline(v = 0, lty = 3)
The plot should end up in the first quadrant with yaxis values increasing from 0 upwards to +###.
The axis(2, ...) line draws the y axis. You can see that is the labels follow a descending sequence: seq(length(list.vlevel), 1, -1). seq(1, length(list.vlevel))
Similarly, inside lines(), probably you need to make the same change from seq(length(list.vlevel), 1, -1) to ``seq(1, length(list.vlevel))`
That's as much as we can tell with the info you've provided - can't run any of yoru code without values for all the constants you use, e.g., biasarray.var.runhour, list.var.bias, vv, etc.
I want to create a figure where for various reasons I need to specify the axis labels myself. But when I specify my labels (some have one digit, some two digits) R suppresses every other two-digit label because it decides there isn't enough room to show them all, but it leaves all of the one-digit labels, leaving the axis looking lopsided.
Is there a way to suppress labels consistently across the whole axis, based on whether any of them need to be skipped? Note: I have a lot of plots with varying scales, so I was looking for something I could use for all of them - I don't want to render all the labels for every plot, or to skip every other label in every plot. Suppressing labels will be desirable for some plots and not for others. I just want to skip every other label consistently, if that's what R chooses to do for the particular plot.
(Here is an example figure of what I mean. What I want is for the "6%" label to also be suppressed in the x axis.)
Example code:
library(labeling)
df <- data.frame("estimate" = c(9.81, 14.29, 12.94),
"lower" = c(4.54, 6.25, 5.12),
"upper" = c(12.85, 20.12, 15.84))
ticks <- extended(min(df$lower), max(df$upper), m = 5, only.loose = TRUE,
Q=c(2, 5, 10))
png("examplePlot.png", width = 1200, height = 900, pointsize = 10, res = 300)
bars <- barplot(df$estimate, horiz = TRUE, col = "white", border = NA,
xlim = c(min(ticks), max(ticks)), xaxt = "n", main = "Example")
arrows(df$lower, bars, df$upper, bars, code = 3, angle = 90, length = 0.03)
points(df$estimate, bars, pch = 20)
tickLabels <- paste(ticks, "%", sep = "")
axis(1, at=ticks, labels = tickLabels, cex.axis=1)
axis(2, at = bars, labels = c("c", "b", "a"), lwd = 0, las = 2)
dev.off()
This depends on the size of the plot, so you'll have to plot each label separately:
axis(1, lwd.ticks = 1, labels = FALSE, at = ticks) # plot line and ticks
i <- seq(1,length(ticks),2) # which labels to plot
for(ii in i)
axis(1, at = ticks[ii], labels = tickLabels[ii], cex.axis = 1, lwd = 0)
I have plotted five graphs and a legend. The graphs work just fine, however the legens disappears without an error.
My preview in RStudio looks like this
When I zoom in, the area where the legend should be is blank.
I use the following code:
opar <- par (no.readonly = TRUE)
par (mfrow = c(3, 2))
library(deSolve)
# Plot A
LotVmod <- function (Time, State, Pars) {
with(as.list(c(State, Pars)), {
dx = (b*x) - (b*x*x/K) - (y*(x^k/(x^k+C^k)*(l*x/(1+l*h*x))))
dy = (y*e*(x^k/(x^k+C^k)*(l*x/(1+l*h*x)))) - (m*y)
return(list(c(dx, dy)))
})
}
Pars <- c(b = 1.080, e = 2.200, K = 130.000, k = 20.000, l = 2.000,
h = 0.030, C = 2.900, m = 0.050)
State <- c(x = 0.25, y = 2.75)
Time <- seq(1, 9, by = 1)
out <- as.data.frame(ode(func = LotVmod, y = State, parms = Pars, times = Time))
matplot(out[,-1], type = "l", xlim = c(1, 9), ylim = c(0, 45),
xlab = "time",
ylab = "population",
main = "Compartment A")
mtext ( "Coefficient of Variance 4.96", cex = 0.8 )
x <- c(# Validation data)
y <- c(# Validation data)
lines (Time, x, type="l", lty=1, lwd=2.5, col="black")
lines (Time, y, type="l", lty=1, lwd=2.5, col="red")
# Legend
plot.new()
legend("center", c(expression (italic ("F. occidentalis")*" observed"),
expression (italic ("M. pygmaeus")*" observed"),
expression (italic ("F. occidentalis")*" simulated"),
expression (italic ("M. pygmaeus")*" simulated")),
lty = c(1, 1, 1, 2),
col = c(1, 2, 1, 2),
lwd = c(2.5, 2.5, 1, 1),
box.lwd = 0, bty = "n")
# Plot C to F = same as A
par(opar)
My output doesn't give an error. I have used the exact same code before without any trouble, thus I restarted R, removed all objects, cleared all plots and restarted both RStudio and my computer.
Try to add xpd=TRUE in your legend statement. I.e.
legend("center", c(expression (italic ("F. occidentalis")*" observed"),
expression (italic ("M. pygmaeus")*" observed"),
expression (italic ("F. occidentalis")*" simulated"),
expression (italic ("M. pygmaeus")*" simulated")),
lty = c(1, 1, 1, 2),
col = c(1, 2, 1, 2),
lwd = c(2.5, 2.5, 1, 1),
box.lwd = 0, bty = "n", xpd=TRUE)
By default, the legend is cut off by the plotting region. This xpd parameter enables plotting outside the plot region. See e.g. ?par for more on xpd.
This is due to how the plot canvas is set up and how rescaling that device works. The way you do it, you add the legend in the plotting region of the top right plot. The plotting region is however not the complete device, but only the part inside the space formed by the axes. If you rescale, that plotting region will be rescaled as well. The margins around the plotting region don't change size though, so zooming in makes your plotting region so small that it doesn't fit the legend any longer. It is hidden by the margins around the plotting region.
For that reason AEBilgrau is very right you need to add xpd = TRUE. This allows the legend to extend outside of the plotting region, so it doesn't disappear behind the margins when resizing the plotting device.
I don't know how to change the code so that the y-axis in the barPlot shows completely? I expect it to show up to 10 as I have a 9.2 in my data points but it shows only up to 8. Any idea what's the hack to this?
Here's the code:
And here's what it shows:
just set the ylim = c(0, 10) like the way you changed the xlim
Whatever the axis that the groups go on isn't drawn by default, so a vertical bar plot won't have x-axis; horizontal won't have y-axis. You can add that of course. Use the return value of barplot:
par(mfrow = c(2, 1))
bp <- barplot(c(8, 5), width = .5, main = 'Feature Exploration', xlim = c(0,4), ylim = c(0, 10),
ylab = 'Errors (%)', xlab = 'ML Models', col = c('gray27','orangered4'))
## this will draw the x-axis but at points 1, 2, 3, ... which is not
## where the centers of your bars are plotted; you get that info in bp
axis(1)
bp <- barplot(c(8, 5), width = .5, main = 'Feature Exploration', xlim = c(0,4), ylim = c(0, 10),
ylab = 'Errors (%)', xlab = 'ML Models', col = c('gray27','orangered4'))
## so try again with a fancy axis, bp is a matrix containing the centers
## of the plotted bars
axis(1, at = bp, labels = c('Model1','Model2'), lwd = 0, lwd.ticks = 1, tcl = -.5)