I found, that axes were rescaled during multiple plotting using par(new=T) parameter.
An example to demonstrate this:
a <- seq(1,10, by = 0.25)
b <- sin(a)
c <- sin(2*a)+1
d <- sin(0.5*a)+2
df <- data.frame(a,b,c,d)
plot(df$a, df$b, type="l")
par(new=T)
plot(df$a, df$c, type="l", col="blue")
par(new=T)
plot(df$a, df$d, type="l", col="red")
This is the result.
Instead of real scales, I have a transformed curves.
And this is the real result:
I used parameters axes=F, xlab="", ylab="" and did not see this "rescaling".
I find it very dangerous, that it is so easy to transform the data during plotting if you do not control y-limits.
Are there better ways to control y-limits than looking for min and max values in all plotted data to avoid this "rescaling" effect?
I have several quite big files and each of them gives only one line from 10 in one plot and I have several plots on one page to compare my data.
The code for the last "correct" image:
plot(df$a, df$b, type="l", ylim=c(-1.5,3.5))
par(new=T)
plot(df$a, df$c, type="l", ylim=c(-1.5,3.5), col="blue", axes=F, xlab="", ylab="")
par(new=T)
plot(df$a, df$d, type="l", ylim=c(-1.5,3.5), col="red", axes=F, xlab="", ylab="")
#Create an empty plot with enough xlim and ylim to accomodate all data
plot(1, 1, xlim = range(df[,1]), ylim = range(df[,-1]), type = "n", ann = FALSE)
#Draw the three lines
lines(df$a, df$b)
lines(df$a, df$c, col="blue")
lines(df$a, df$d, col="red")
Related
I'm working with GLMs and therefore do some plots with the "visreg" package, and I also add usual plots to them. My script looks like this:
library(visreg)
visreg(model01, scale = "response", type="conditional",line=list(col="green"), ylim=c(0,1), xlim=c(0,400), rug=F, axes=F, ann=F)
par(new=T)
plot(data$x ~ data$y, ylim=c(0,1), xlim=c(0,400), col=rgb(0,100,50,50, maxColorValue=255), pch=19, cex=2, axes=F, ann=F)
par(new=T)
visreg(model02, scale = "response", type="conditional",line=list(col="red"), ylim=c(0,1), xlim=c(0,400), rug=F, axes=F, ann=F )
par(new=T)
plot(data$x ~ data$z, ylim=c(0,1), xlim=c(0,400), col=rgb(0,50,100,50, maxColorValue=255), pch=19, cex=2, las=1, xlab="label01", ylab="label02")
axis(1)
axis(2, las=1)
box()
col1 <- c(rgb(0,100,50, maxColorValue=155), rgb(0,50,100, maxColorValue=155))
legend (315, 1.05, legend=c("bla01", "bla02"), col=c("green","red"), y.intersp=1.3, cex=0.9, lty=1, lwd=2, bty="n")
legend (309, 1.06, legend=c("",""), col=col1, pch=19, y.intersp=1.2, bty="n")
The visreg() parts plot the regression model while the plot() parts plot the corresponding data. The whole plot looks the way I want it in RStudio, but when I export it as a metafile I loose the plot() parts of it (except the axis labels, they are still there). Does anybody know why that is and what I can do to export it all as a metafile?
Cheers,
Alex
I have the following data and code in R:
x <- runif(1000, -9.99, 9.99)
mx <- mean(x)
stdevs_3 <- mx + c(-3, +3) * sd(x/5) # Statndard Deviation 3-sigma
And I plotted as line (alongwith 3 standard deviation and mean lines) in R:
plot(x, t="l", main="Plot of Data", ylab="X", xlab="")
abline(h=mx, col="red", lwd=2)
abline(h=stdevs_3, lwd=2, col="blue")
What I want to do:
Anywhere on the plot, whenever line is crossing 3 sigma thresholds (blue lines), above or below it, line should be in different color than black.
I tried this, but did not work:
plot(x, type="l", col= ifelse(x < stdevs_3[[1]],"red", "black"))
abline(h=mx, col="red", lwd=2)
abline(h=stdevs_3, lwd=2, col="blue")
Is there any other way?
This is what is requested, but it appears meaningless to me because of the arbitrary division of x by 5:
png( )
plot(NA, xlim=c(0,length(x)), ylim=range(x), main="Plot of Data", ylab="X", xlab="", )
stdevs_3 <- mx + c(-3, +3) * sd(x/5)
abline(h=mx, col="red", lwd=2)
abline(h=stdevs_3, lwd=2, col="blue")
segments( 0:999, head(x,-1), 1:1000, tail(x,-1) , col=c("black", "red")[
1+(abs(tail(x,-1)) > mx+3*sd(x/5))] )
dev.off()
Is it possible to rearrange the legend of the following plot
plot(1,1, type="n")
legend("topleft", c("1", "2"), col=c("darkblue", "darkred"), pch = 1, bty = "n", horiz = T, lwd=1.25, cex=1.8)
to look like this ("point-line-point" pattern)?
Usually, if you want this level of control over plot elements, you'll have to do it manually with primitives (points(), lines()/segments(), text(), etc.) and careful calculations from the plot parameters (e.g. par('usr')). It's not easy. Here's an example of how this could be done:
point.line.point <- function(x1,y1,x2=x1,y2=y1,...) {
points(c(x1,x2),c(y1,y2),...);
segments(x1,y1,x2,y2,...);
};
legend.plp <- function(x,y,labels,col,linewidth=diff(par('usr')[1:2])/10,textgap=diff(par('usr')[1:2])/20,...) {
comb <- cbind(labels,col);
xc <- x;
for (i in seq_len(nrow(comb))) {
x2 <- xc+linewidth;
point.line.point(xc,y,x2,col=comb[i,'col'],...);
text(x2+textgap,y,comb[i,'labels'],...);
xc <- x2+textgap*1.5+strwidth(comb[i,'labels']);
};
};
plot(1,1,type="n");
legend.plp(par('usr')[1]+diff(par('usr')[1:2])/20,par('usr')[4]-diff(par('usr')[3:4])/20,1:2,c('darkblue','darkred'),font=2,cex=1.5);
Here is an alternative solution that is the opposite of elegant. It involves embedding a couple of plots (one per legend), and a great deal of manual manipulation (to set the 'legends' where you want them to be):
library(Hmisc)
data(mtcars)
#plots the one in blue
plot(mtcars$cyl, type="o", col="darkblue")
#plots the one in red
lines(mtcars$carb, type="o", col="darkred")
#name the legends
text(6.5,7, "Cyl", font=2)
text(14,7, "Carb", font=2)
#add the subplots, it's actually a normal plot wrapped around the subplot with the x and y positions
subplot(plot(c(1,0),c(1,1), xlab=NA, ylab=NA, xaxt="n", yaxt="n", col="darkblue", type="o", axes=FALSE), 3, 7)
subplot(plot(c(1,0),c(1,1), xlab=NA, ylab=NA, xaxt="n", yaxt="n", col="darkred", type="o", axes=FALSE), 10, 7)
That yields the following plot:
I'm trying to plot multiple line plots against a single bar plot (in this example it's grouped but doesn't have to be) but I'm running into some issues with left y-axis resizing in strange ways. It seems ok-ish when there are two lines, but then extends the axis out when there are more so the scale is wrong and doesn't line up with the bars.
I need to end up with a situation where I can customise the labels on both the left and right y-axes, hence the use of axis at the bottom of the code. In the real implementation I'll be dynamically using 'M' for million or 'K' for thousand on the left, and '%' on the right.
Any help would be very much appreciated.
x = c("a","b","c","d")
y= cbind(c(50,40,30,20), c(40,30,20,10))
y2 = c(0.80,0.65,0.75,0.50)
y3 = c(0.30,0.20,0.50,0.60)
y4 = c(0.20,0.30,0.40,0.45)
#
par(mar=c(5,8,3,5))
bp <- barplot(t(y), beside=TRUE, las=1, names.arg=x, axes=TRUE, ylim=c(0,max(y)+10), labels=c("0","10 M","20 M","30 M","40 M","50 M","60 M"))
xlim <- c(floor(min(bp)), ceiling(max(bp)))
#
par(new=T)
plot(colMeans(bp), y2, type="o", col="black", lwd=3, lty=1, xaxt="n", yaxt="n", xlab="", ylab="", xlim = xlim)
points(colMeans(bp), y2, pch=20)
par(new=T)
plot(colMeans(bp), y3, type="o", col="red", lwd=3, lty=1, xaxt="n", yaxt="n", xlab="", ylab="", xlim = xlim)
points(colMeans(bp), y3, pch=20)
par(new=T)
plot(colMeans(bp), y4, type="o", col="red", lwd=3, lty=1, xaxt="n", yaxt="n", xlab="", ylab="", xlim = xlim)
points(colMeans(bp), y4, pch=20)
axis(side=2, at=c(0,0.10,0.20,0.30,0.40,0.50,0.60), labels=c("0","10 M","20 M","30 M","40 M","50 M","60 M"), las=1, pos=0.555)
axis(side=4, pretty(c(0,max(y2))), ylim=c(0,max(y2)), col='black', ylab='', las=1 )
You can use the lines() argument for the second and third line, the everything works fine. Here is an example for the third Line:
#par(new=T)
lines(colMeans(bp), y4, type="o", col="red", lwd=3, lty=1)
points(colMeans(bp), y4, pch=20)
Assuming I have two data sets I'd like to plot in one plot.
For instance something like this:
low <- runif(10,min=10, max=50)
high <- runif(10,min=10000, max=11000)
plot(
high,
type="l",
ylim=c(0,11000)
)
lines(low, type="l")
I dont want the y-axis to show all values in between these samples because the way it is, the low data would appear as flat line, even though there are variations.
Therefore, the axis should have a finer grained ticks between 10-50, and should omit values between 50 and 10000. Then again, the interval [10000-11000] should have finer grained ticks, too. Thus, variations for the low sample are also visible.
Is there any way to achieve this behavior?
If found this, bt
Could this be useful...?
set.seed(001)
low <- runif(10,min=10, max=50)
high <- runif(10,min=10000, max=11000)
plot(
high,
type="l",
ylim=c(0,11000)
)
lines(low, type="l")
plot(high,
type="l",
col="red",
bty='l',
ylab='', xlab='',
las=1,
cex.axis=.75)
par(new=TRUE)
plot(low,
type="l",
col="blue",
bty='n',
xaxt="n",
yaxt="n",
xlab="", ylab="",
cex.axis=.75)
axis(4, las=1, cex.axis=.75)
legend('topright', c('high', 'low'), col=c('red', 'blue'), lty=1, bty='n', cex=.75)
Questions of good graphical practice aside, this can be done using the plotrix package:
low <- runif(10,min=10, max=50)
high <- runif(10,min=10000, max=11000)
y <- c(low,high)
x <- rep(1:10,times = 2)
library(plotrix)
yl <- c(pretty(5:70,2),pretty(9900:11000,5))
gap.plot(x,y,
gap = c(70,9900),
gap.axis = "y",
ytics = yl,
type = "l")