Related
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.
In R, I've created a plot with a separate axis on the left to specify horizontal labels for the y-axis of the plot. However, the labels are truncated. That is, the complete name is not shown, only the last 9 characters of the name is shown. I use the R axis command to create the axis and the labels = names parameter to specify the names. names is a vector of character label names which vary in length.
plot(x = c(0,mx),y=c(1,n),yaxt = 'n', xlab = "Dollars - 100,000's", cex.axis = .65, typ = 'n', ylab = '', cex.lab = .8)
axis(side = 2, at = seq(1,n), labels = names, las = 2, cex.axis = .65)
Here's what the plot looks like:
Plot with truncated names
You can modify the margin of your plot by passing the mar argument to par function:
mar.default <- c(5,4,4,2) + 0.1
par(mar = mar.default + c(0, 4, 0, 0))
plot(x = c(0,mx),y=c(1,n),yaxt = 'n', xlab = "Dollars - 100,000's", cex.axis = .65, typ = 'n', ylab = '', cex.lab = .8)
axis(side = 2, at = seq(1,n), labels = names, las = 2, cex.axis = .65)
Without a reproducible example of your dataset, I can't guarantee that it will work right away, maybe you will have to adjust it on your own.
Otherwise, you can provide a reproducible example of your data: How to make a great R reproducible example
I want to add country labels (actually ten) to a rworldmap. Two of them overlap because they're small, bordering states. I want to move one of them a little to the side, but keep the first one in place.
I think I don't need to show the rworldmap code here since I could break down the issue to the text function.
From the function's arguments defaults
text(x, y = NULL, labels = seq_along(x$x), adj = NULL,
pos = NULL, offset = 0.5, vfont = NULL,
cex = 1, col = NULL, font = NULL, ...)
I would conclude that the default pos is NULL, so I say pos=c(NULL, 4). However this doesn't work as expected; the first label is also moved. The moveString is moved correctly, but the other should stay where it is. I have tried all available pos for the stayString, but they do not correspond to the original position. I also tried adj with no success.
plot(0:3, type="n")
grid()
text(c(2, 2.2), rep(3, 2), c("stayString", "moveString"),
col="black") # raw
text(c(2, 2.2), rep(2.5, 2), c("stayString", "moveString"),
pos=c(NULL, 4), col="red") # unexpected result
# other attempts
text(c(2, 2.2), rep(2, 2), c("stayString", "moveString"),
pos=c(1, 4), col="green")
text(c(2, 2.2), rep(1.5, 2), c("stayString", "moveString"),
adj=c(.5, 1), col="blue")
text(c(2, 2.2), rep(1, 2), c("stayString", "moveString"),
pos=c(2, 4), col="purple")
text(c(2, 2.2), rep(.5, 2), c("stayString", "moveString"),
pos=c(1, 4), adj=c(.5, 1), col="orange")
I am rather looking for such an adjustment solution because I don't like to change the coordinates since they nicely represent the center of each country.
How can I move the moveString and keep the stayString in position without changing the x/y coordinates?
A solution that comes to mind is to create two functions, and split each string based on the fact that you want to offset it or not.
We can use, from text(), pos and offset to move the text a little.
text_stay <- function(x, y, lab, ...) {
text(x,y, labels=lab, ...)
}
text_move <- function(x,y,lab, p=4, off=2, ...) {
text(x, y, labels=lab, pos=p, offset=off, ...)
}
So for example:
plot(0:3, type="n")
grid()
# split the text and use the appropriate wrapper function
text_stay(rep(2, 3), 1:3, "stay", col="red")
text_move(rep(2, 3), 1:3, "move", col = "blue")
I have the following code:
plot(x = 1, y = 1, xlim = c(1,2), ylim = c(1,2),
ylab = expression(bgroup("(",A[B]^{C},")")[~D[2]] / bgroup("(",E[F]^{G},")")[~H]))
Which leads to this plot:
Is it possible to make the division symbol ("/") taller so it properly divides two expression and doesn't look like it's shooting out of D2?
My attempt at manually drawing it with cex>1 lead to an ugly and fat division symbol. I don't want it fatter, just taller.
I am looking for solutions that use base plot methods.
If you don't mind using latex, you can export the plot using tickz. That will unleash the full power of latex formatting. E.g. with a standard sized division sign it looks like this:
library(devtools)
install_github('daqana/tikzDevice')
library(tikzDevice)
tikz('test.tex', width = 4, height = 3)
par(mar=c(3,6,3,3))
plot(x = 1, y = 1,
xlim = c(1,2), ylim = c(1,2),
ylab = '$(A_B^C)_{D_2} / (E_F^G)_{H}$')
dev.off()
or if you want an even bigger division sign, you can use one of the latex codes (in ascending order of size) \big/, \Big/, \bigg/, or \Bigg/:
tikz('test.tex', width = 4, height = 3)
par(mar=c(3,6,3,3))
plot(x = 1, y = 1,
xlim = c(1,2), ylim = c(1,2),
ylab = '$\\left(A_B^C\\right)_{D_2} \\bigg/ \\left(E_F^G\\right)_{H}$')
dev.off()
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.