Line Graph Overlaying bar graph in base r - 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)

Related

How to remove the vertical asymptote using curve function in 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)

How to move y-axis labels away from R plot using lapply in R

I have the following code (Thanks to an answer from #Rawr in this question):
labes1 <- c("P(LNG)","","Volume(LNG)","","P(oil)","","Can.GDP","","US GDP","")
titles <- c("Levels","","","","","Log Difference","","","","")
par(mfrow = c(5, 2), mar = c(0.3, 6, 0, 2), oma = c(5, 0, 3, 2))
lapply(1:10, function(ii) {
x <- plotdata1[, ii, drop = FALSE]
plot(x, xlab = "Quarter", ylab = labes1[ii], axes = FALSE)
axis(2, las = 1)
box()
if (ii %in% 9:10) {
axis(1)
title(xlab = 'Quarter', xpd = NA)
}
if (ii %in% 1:2)
title(main = c('Levels', 'Log Difference')[ii], xpd = NA, line = 1)
})
This produces the following plot:
The obvious issue is the overlaying of the y-axis labels with the y-axis values. I have tried playing around with the mar() and oma() but these just change the margins around, I was hoping this would move things out of the way. How can I move the y-axis labels as separate from the plot? I will also be moving the margins a bit so that the white space between the two columns of plots will be closer together.
You can define the ylab separately, like what you're doing for the xlab, and set the line parameter to define its distance from the plot (as stated in this post).
I got a running example from combining your code and #rawr's from your previous question.
set.seed(1)
z <- ts(matrix(rt(200 * 10, df = 3), 200, 10), start = c(1961, 1), frequency = 12)
z <- z * 1e5 # to make "wide" y-axis labels
## vectors of x, y, and main labels
xl <- sprintf('x label %s', 1:10)
yl <- sprintf('y label %s', 1:10)
ml <- sprintf('main label %s', 1:10)
labes1 <- c("P(LNG)","","Volume(LNG)","","P(oil)","","Can.GDP","","US GDP","")
titles <- c("Levels","","","","","Log Difference","","","","")
par(mfrow = c(5, 2), mar = c(0.3, 6, 0, 2), oma = c(5, 0, 3, 2))
lapply(1:10, function(ii) {
x <- z[, ii, drop = FALSE]
plot(x, xlab = "Quarter", ylab = "", axes = FALSE) # set ylab to ""
axis(2, las = 1)
title(ylab = labes1[ii], line = 4) # set the line at an appropriate distance
box()
if (ii %in% 9:10) {
axis(1)
title(xlab = 'Quarter', xpd = NA)
}
if (ii %in% 1:2)
title(main = c('Levels', 'Log Difference')[ii], xpd = NA, line = 1)
})
The code above outputs the following graph for line = 4 :
and this plot for line = 3 :

Overlaying and staggering two plots with different y axes

I am looking for advice for plotting 2 similar wave forms with different y axes scales (one is mmHg and another is m/s) in the same plot. However, I would like to stagger the plots with respect to each other.
For example, using the below:
set.seed(123)
y <- sin(2*pi*x)
g <- sin(2*pi*x)+ rnorm(200, sd=0.1)
plot(y,type="l",
ann = F,
axes = F)
axis(side = 2)
par(new = T)
plot(g,type="l",
ann = F,
axes = F)
axis(side = 4)
Gives:
I would like to achieve something like this (see link below):
How to achieve this?
Here's a slightly cheaty solution:
x <- seq(from = 1, to = 3, by = 0.01)
y <- sin(2*pi*x)
set.seed(123)
g <- sin(2*pi*x)+ rnorm(length(x), sd=0.1)
stagger <- 2
glabels <- c(-1, 0, 1)
plot(c(min(y),max(y)+stagger) ~ c(1,length(y)), type="n", axes=FALSE, ann=FALSE)
lines(y)
axis(side = 2, at = min(y):max(y))
par(new = T)
lines(g+stagger)
axis(side = 4, at = glabels + stagger, labels = glabels)
Results in:
There's probably a better way to generate the positions and labels for the y-axis for g.

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)

plot axis labels with multiple colours

I'm making plots like the one generated with the following code:
var1 <- sort(runif(10, 0, 1), decreasing = TRUE)
var2 <- sort(runif(10, 0, 1))
plot(var1, pch = 20, ylab = c("Var 1", "Var 2"))
points(var2, pch = 20, col = "grey")
Is there a way, with just the R graphics package, to place a black circle before Var 1 and a grey circle before Var 2 in the y axis label, to avoid having to insert a legend? Or alternatively, a way to use different text colours (black for Var 1 and grey for Var 2) in the y axis? I tried using col.lab = c("black","grey"), but it says Error in plot.window(...) : graphical parameter "col.lab" has the wrong length.
Many thanks in advance,
Márcia
I'm not sure how to add the point to the label, but an easy way to labe with color can be done in the following way:
var1 <- sort(runif(10, 0, 1), decreasing = TRUE)
var2 <- sort(runif(10, 0, 1))
plot(var1, pch = 20, ylab = "")
points(var2, pch = 20, col = "grey")
mtext("Var 1", side=2, line=2)
mtext("Var 2", side=2, line=3, col="grey")
Would something like this work for you? It's a bit busy on the left axis, but I think it shows what you are asking about.
> var1 <- sort(runif(10, 0, 1), decreasing = TRUE)
> var2 <- sort(runif(10, 0, 1))
> plot(var1, ylim = range(c(var1, var2)), pch = 20, ylab = "", axes = FALSE)
> points(var2, pch = 20, col = "grey")
> labs <- round(sort(c(var1, var2)), 1)
> axis(1)
> axis(2, at = sort(c(var1, var2)), labels = labs)
> sapply(var1, function(x) points(-0.1, x, pch = 20))
> sapply(var2, function(x) points(-0.1, x, pch = 20, col = "grey"))
> box()

Resources