How to remove the vertical asymptote using curve function in R - r

curve(
(x+3)/(x+2),
from = -9,
to = 6,
xlab = "",
ylab = "",
# xlim = ,
ylim = c(-0.5,2.5),
las = 1,
lwd = 2
)
How can I remove the vertical black line in this plot?
So I can add it myself using
abline(
v = -2,
h = 1,
lty = 2,
col = 2,
lwd = 2
)
Update
Is there a "global" option to modify this?
If I have to change this toleranace or draw it piecewise for every function I use, it would be tedious ....

n <- 1e3
from <- -9
to <- 6
tol <- (to - from) / n
curve(
ifelse(abs(x + 2) > tol, (x+3)/(x+2), NA),
from = from,
to = to,
n = n,
xlab = "",
ylab = "",
# xlim = ,
ylim = c(-0.5,2.5),
las = 1,
lwd = 2
)

The reason it does that is because the "continuous" domain of x hits the most-nonzero finite y (negative) that R recognizes and then starts again at the most nonzero finite y (positive) and continues the line through those two points. The answer to this is to stop the curve immediately before that point (x = -2) and draw a second line just after that point, adding xlim= to the first call and add=TRUE to the second. (Most of the options are not needed or even used when add=TRUE, so I'll omit them here for demonstration of "simple".)
curve(
(x+3)/(x+2),
from = -9,
to = -2.1,
xlab = "",
ylab = "",
xlim = c(-9, 6),
ylim = c(-0.5,2.5),
las = 1,
lwd = 2
)
curve(
(x+3)/(x+2),
from = -1.9,
to = 6,
lwd = 2,
add = TRUE)

Related

Trajectory error in phase plane for ODEs in R (PhaseR Package)

I am trying to plot the trajectory of the ODE in R but I am getting this weird error. I am able to plot the nullclines of the phase plane but I am not able to plot the trajectory of the system. (In my case, the parameters are a and b, but I'm not sure what to do with the function call parameters here. This is from the default function I was given. Should I remove it in the function call?)
PeriodicSystem <- function(t, y, parameters) {
a <- a
b <- b
dx <- -x + (a*y) + ((x^2)*y)
dy <- b - (a*y) + ((x^2)*y)
list(c(dx,dy))
}
example4_flowField <- flowField(PeriodicSystem,
xlim = c(-0.01, .425),
ylim = c(0, .5),
add = FALSE,
ylab = TeX("$y$"),
xlab= TeX("$x$"),
frac=1,
add.legend=FALSE)
grid()
example4_nullclines <- nullclines(PeriodicSystem,
xlim = c(-0.01, .425),
ylim = c(0, .5),
lty = 2, lwd = 2,
col=c("lightseagreen","aquamarine4"),
add.legend=FALSE)
example4_flowField <- flowField(PeriodicSystem,
xlim = c(-0.01, .425),
ylim = c(0, .5),
add = FALSE,
ylab = TeX("$y$"),
xlab= TeX("$x$"),
frac=1,
add.legend=FALSE)
grid()
example4_nullclines <- nullclines(PeriodicSystem,
xlim = c(-0.01, .425),
ylim = c(0, .5),
lty = 2, lwd = 2,
col=c("lightseagreen","aquamarine4"),
add.legend=FALSE)
y0 <- matrix(c(0.1,0.3,
0,0,
0.1,0.2), 3, 2, byrow = TRUE)
example4_trajectory <- trajectory(PeriodicSystem,
y0 = y0,
pch=16,
tlim = c(0, 100),
col="black",
add=T, ylab=TeX("$x, y$"), xlab=TeX("$t$"))
grid()
Note: col has been reset as required
Error in checkFuncEuler(Func, times, y, parms, rho, Nstates) :
The number of derivatives returned by func() (1000must equal the length of the initial conditions vector (2)

R is plotting y axis upside down. How to flip rightside up?

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.

How to plot (almost) the same function at both sides of the "y" axis in R?

I have a function that depends on distance and behaves different according to the direction (east or west) to where you evaluate it. Now I have two plots side by side, but I need to have them as one, where the labels of the axis are shared and the x axis label is centered. Here is an example of how the code looks right now:
x = (0:300)
par(mfrow=c(2,2))
Idriss70 = function(x){
exp(5.6315-0.4104*7-(2.9832-0.2339*7)*log(x+10)+0.00047*x+0.12)
}
plot(Idriss70(x), log = "x", type="l",xlim = c(300,1), xlab="Distancia [km]",ylab="PGA [g]", main="Aroma y Humayani extendida, Mw 7,0", col="green", panel.first = grid(equilogs = TRUE))
Idriss70 = function(x){
ifelse (x >= 0 & x<=3, exp(5.6315-0.4104*7-(2.9832-0.2339*7)*log(0+10)+0.00047*0+0.12),
exp(5.6315-0.4104*7-(2.9832-0.2339*7)*log(x+10)+0.00047*x+0.12))
}
plot(Idriss70(x), log = "x", type="l", xlab="Distancia [km]",ylab="PGA [g]", main="Aroma y Humayani extendida, Mw 7,0", col="green", panel.first = grid(equilogs = TRUE))
As you can see, the log scale of the plots don't allow "negative" values to be evaluated so I haven't been able to use only one plot.
How can I get this plot as one without using Illustrator or another graphics software, as I have to create lots of this ones for differente areas?
I haven't used ggplot in the past but I am willing to learn if necessary.
You can basically make one plot and mess around with fig so that you restrict the first plot to the left half of the device and the second to the right half
x <- 0:300
Idriss70 = function(x){
exp(5.6315-0.4104*7-(2.9832-0.2339*7)*log(x+10)+0.00047*x+0.12)
}
Idriss71 = function(x){
ifelse(x >= 0 & x<=3,
exp(5.6315-0.4104*7-(2.9832-0.2339*7)*log(0+10)+0.00047*0+0.12),
exp(5.6315-0.4104*7-(2.9832-0.2339*7)*log(x+10)+0.00047*x+0.12))
}
par(fig = c(0, .5, 0, 1), mar = c(5, 4, 4, 0), xaxs = 'i', ann = FALSE)
plot(Idriss70(x), log = "x", type="l", xlim = c(300,1),
col="green", axes = FALSE, panel.first = grid(equilogs = TRUE))
xx <- axis(1)
axis(2)
par(fig = c(.5, 1, 0, 1), new = TRUE, mar = c(5, 0, 4, 2))
plot(Idriss71(x), log = "x", type="l", col="green",
panel.first = grid(equilogs = TRUE), axes = FALSE)
axis(1, at = xx, labels = c('', xx[-1]))
title(xlab = "Distancia [km]", main = 'Aroma y Humayani extendida, Mw 7,0',
ylab = 'PGA [g]', outer = TRUE, line = -1.5)
good luck with ggplot. you'd probably have to summon #baptiste
well you could still use mfrow I suppose
graphics.off()
par(mfrow = c(1, 2), mar = c(5, 4, 4, 0), xaxs = 'i', ann = FALSE)
plot(Idriss70(x), log = "x", type="l", xlim = c(300,1),
col="green", axes = FALSE, panel.first = grid(equilogs = TRUE))
xx <- axis(1)
axis(2)
par(mar = c(5, 0, 4, 2))
plot(Idriss71(x), log = "x", type="l", col="green",
panel.first = grid(equilogs = TRUE), axes = FALSE)
axis(1, at = xx, labels = c('', xx[-1]))
title(xlab = "Distancia [km]", main = 'Aroma y Humayani extendida, Mw 7,0',
ylab = 'PGA [g]', outer = TRUE, line = -1.5)

Line Graph Overlaying bar graph in base r

I have written the following code below. I would like to overlay a bar graph with a line graph. The code I have does it all but with just one problem. I would like the points on the line graph to be in the center of the bar graph, i.e. they should shift to the left a little bit. where Im I missing it? If this can be done in ggplot as well I would be happy too. but even base r would do
par(mai = c ( 1 , 2, 1, 1), omi = c(0, 0, 0, 0))
yy <- c(31,31,31,50,50,61,69,75,80,88,94,101,108,115,121,124,125,125,125,126,127)
name1 <- c ("15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35")
xx <- barplot(yy, ylab = "", names.arg = name1, ylim = c(0, 140),col="steelblue")
text(xx, yy + 3, labels = as.character(yy),srt=45)
mtext(2,text="",line=2)
par(new = T)
xx2 <- c(15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35)
yy2 <- c(379,474,579,725,922,1181,1473,1846,2316,2962,3688,4786,6069,7605,9504,10680,11074,11074,11074,11483,11484)
plot(xx2, yy2, xlim = c(14, 36), ylim = c(0, 14000),type ="n" , axes = F, xlab ="", ylab ="",col="blue",main="")
lines(xx2, yy2, lwd = 2,col="red",lty=1)
points(xx2, yy2, pch = 18, cex = 1,col="red")
text(xx2, yy2 + 4 , labels = as.character(yy2),srt=90)
par(new = T)
par(mai = c ( 1 , 1, 1, 1))
axis(2)
mtext(2,text="",line=2.5)
mtext("",side=1,col="black",line=2)
grid()
It can be quote tricky to get things to line up if you use barplot and a standard plot(). I recommend only calling plot once. In order to do this, you will need to rescale your yy2 values to the same scale as yy. Here's how you might do that
par(mai = c ( 1 , 2, 1, 1), omi = c(0, 0, 0, 0))
yy <- c(31,31,31,50,50,61,69,75,80,88,94,101,108,115,121,124,125,125,125,126,127)
name1 <- c ("15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35")
#draw bar plot
xx <- barplot(yy, ylab = "", names.arg = name1, ylim = c(0, 140),col="steelblue")
text(xx, yy + 3, labels = as.character(yy),srt=45)
mtext(2,text="",line=2)
xx2 <- xx #c(15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35)
yy2 <- c(379,474,579,725,922,1181,1473,1846,2316,2962,3688,4786,6069,7605,9504,10680,11074,11074,11074,11483,11484)
#transform data
yy2tx <- yy2/14000 * max(pretty(yy))
#draw line data
lines(xx2, yy2tx, lwd = 2,col="red",lty=1)
points(xx2, yy2tx, pch = 18, cex = 1,col="red")
text(xx2, yy2tx, labels = as.character(yy2),srt=90)
#draw axis for transformed data
par(mai = c ( 1 , 1, 1, 1))
axis(2, at=pretty(c(0,14000))/14000*max(pretty(yy)), labels=pretty(c(0,14000)))
grid()
This produces the following plot
The problem is that you have different x scale due to the different margins of the two plots.
Unless you want to find xx2 by hand... another solution to consider is to use a right y axis instead.
yy <- c(31,31,31,50,50,61,69,75,80,88,94,101,108,115,121,124,125,125,125,126,127)
name1 <- c ("15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35")
xx <- barplot(yy, ylab = "", names.arg = name1, ylim = c(0, 140),col="steelblue")
text(xx, yy + 3, labels = as.character(yy),srt=45)
mtext(2,text="",line=2)
par(new = T)
yy2 <- c(379,474,579,725,922,1181,1473,1846,2316,2962,3688,4786,6069,7605,9504,10680,11074,11074,11074,11483,11484)
plot(xx+0.5, yy2, "l", lwd = 2,col="red",lty=1,
axes=F, ylim=c(0, 14000), xlim=c(min(xx), max(xx)+1))
points(xx+0.5, yy2, pch = 18, cex = 1,col="red")
axis(4)
text(xx+0.5, yy2 + 4 , labels = as.character(yy2),srt=90)

How to plot in a single plot different outputs of a function that internally uses par-mfrow?

I'm using a function that among several things plots the results in two panels using par(mfrow = c(1, 2)).
I would like to run the function with three different datasets and plot the outputs together so that each one is in a row, as if I were using par(mfrow = c(3, 2)).
If there a way of doing this without modifying the function itself?
Probably basic issue, but help very much appreciated.
The function is a little bit long, but the relevant part plots a PCoA:
# perform classical multidimensional sclaing (PCoA) of the dist matrix
acop <- cmdscale(dat.d, k = nrow(as.matrix(dat.d)) - 1, eig = TRUE) # keep n-1 eigenvalues
axes.tot <- acop$eig # eig are the n eigenvalues computed by cmdscale. Axes are ranked by their
eigenvalues, so the first axis has the highest eigenvalue, the second axis has the second highest
eigenvalue, etc.
inertia <- sum(acop$eig[acop$eig > 0])
percents <- round(as.numeric(100 * axes.tot/inertia), digits = 0) # The eigenvalues represent
the variance extracted by each axis, here they are expressed as a percentage of the sum of all
eigenvalues (i.e. total variance).
par()
par(mfrow = c(1, 2), pty = "s")
coord1 <- acop$points[, c(1, 2)] # points is a matrix whose rows give the coordinates of the
points chosen to represent the dissimilarities
col.grps <- data.frame(vect.grps, coord1)
# plot so that the maximum variance is projected along the first axis, then on the second and so
on
plot(coord1, asp = 1, cex = 0.1, xlab = paste("Axis 1 ",
"(", percents[1], " % variance explained)", sep = ""),
ylab = paste("Axis 2 ", "(", percents[2], " % variance explained)",
sep = ""), main = "", type = "n", bty = "n")
abline(h = 0, lty = 2, col = "grey")
abline(v = 0, lty = 2, col = "grey")
if (length(vect.grps) == nrow(as.matrix(dat.d))) {
for (g in 1:length(names.grps)) {
text(x = coord1[col.grps[, 1] == names.grps[g], 1],
y = coord1[col.grps[, 1] == names.grps[g], 2],
labels = names.grps[g], col = topo.col[g], cex = 0.7)
}
}
else {
points(coord1, pch = 19, col = "blue", cex = 0.5)
}
coord1 <- acop$points[, c(3, 4)]
col.grps <- data.frame(vect.grps, coord1)
plot(coord1, asp = 1, cex = 0.1, xlab = paste("Axis 3 ",
"(", percents[3], " % variance explained)", sep = ""),
ylab = paste("Axis 4 ", "(", percents[4], " % variance explained)",
sep = ""), main = "", type = "n", bty = "n")
abline(h = 0, lty = 2, col = "grey")
abline(v = 0, lty = 2, col = "grey")
if (length(vect.grps) == nrow(as.matrix(dat.d))) {
for (g in 1:length(names.grps)) {
text(x = coord1[col.grps[, 1] == names.grps[g], 1],
y = coord1[col.grps[, 1] == names.grps[g], 2],
labels = names.grps[g], col = topo.col[g], cex = 0.7)
}
}
else {
points(coord1, pch = 19, col = "blue", cex = 0.5)
I guess you can overwrite par(),
foo <- function(){
par(mfrow=c(2,1), mar=c(0,0,0,0))
plot(1:10)
plot(rnorm(10))
}
par <- function(mfrow, ...) {graphics::par(mfrow=c(3, 2), ...)}
foo()
rm(par)

Resources