Related
I have this line-and-dots plot:
#generate fake data
xLab <- seq(0, 50, by=5);
yLab <- c(0, sort(runif(10, 0, 1)));
#this value is fixed
fixedVal <- 27.3
#new window
dev.new();
#generate the plot
paste0(plot(xLab, yLab, col=rgb(50/255, 205/255, 50/255, 1), type="o", lwd=3,
main="a line-and-dots plot", xlab="some values", ylab="a percentage",
pch=20, xlim=c(0, 50), ylim=c(0, 1), xaxt="n", cex.lab=1.5, cex.axis=1.5,
cex.main=1.5, cex.sub=1.5));
#set axis
axis(side = 1, at=c(seq(min(xLab), max(xLab), by=5)))
#plot line
abline(v=fixedVal, col="firebrick", lwd=3, lty=1);
now, I would like to find the y coordinate of the intersection point between the green and the red lines.
Can I achieve the goal without the need of a regression line? Is there a simple way of getting the coordinates of that unknown point?
You can use approxfun to do the interpolation:
> approxfun(xLab,yLab)(fixedVal)
[1] 0.3924427
Alternatively, just use approx:
> approx(xLab,yLab,fixedVal)
$x
[1] 27.3
$y
[1] 0.3924427
Quick fix like #JohnColeman said:
# find the two points flanking your value
idx <- findInterval(fixedVal,xLab)
# calculate the deltas
y_delta <- diff(yLab[idx:(idx+1)])
x_delta <- diff(xLab[idx:(idx+1)])
# interpolate...
ycut = (y_delta/x_delta) * (fixedVal-xLab[idx]) + yLab[idx]
ycut
[1] 0.4046399
So we try it on the plot..
paste0(plot(xLab, yLab, col=rgb(50/255, 205/255, 50/255, 1), type="o", lwd=3,
main="a line-and-dots plot", xlab="some values", ylab="a percentage",
pch=20, xlim=c(0, 50), ylim=c(0, 1), xaxt="n", cex.lab=1.5, cex.axis=1.5,
cex.main=1.5, cex.sub=1.5));
#set axis
axis(side = 1, at=c(seq(min(xLab), max(xLab), by=5)))
#plot line
abline(v=fixedVal, col="firebrick", lwd=3, lty=1);
abline(h=ycut, col="lightblue", lwd=3, lty=1);
Can someone help me. I have a dataset that had NA values that I have interpolated with zoo. I have added a 'colour column' in the hope that I could create a line plot (time series) with the interpolated values plotted in a different colour to the rest of the line. That is, the segment of the line defined by the point immediately before and immediately after the interpolated point should be red, and not black.
I've attached an example of my table here (where the colour is 'red' defines the values that have been interpolated). I've also put an image of the graph so far and the desired output here too:
https://drive.google.com/folderview?id=0B_eJi0urUAzFM0JBS1ZIbUdGck0&usp=drive_web
This is my code thus far. The 'lines' part of the code is where I hoped to define the colour as the column in the data frame:
par(mfrow=c(2,1), mar=c(4,4.5,2,2), mgp=c(2,0.6,0))
x.limit <- round(range(UN.GRACE.Int$DecimDate), 2)
plot(NULL, type="n", xlim=x.limit, ylim=c(-20, 25), xlab="Year", ylab="GRACE-TWS (cm)", axes=F)
box(lwd=1.5)
abline(h=0, col="gray50", lty=1)
axis(1, seq(2003, 2012, 1), cex.axis=0.8)
axis(2, seq(-20, 25, 5), las=1, cex.axis=0.8)
minor.tick(nx=4, ny=0, tick.ratio=0.5)
lines(UN.GRACE.Int[,2] ~ UN.GRACE.Int[,1], type="l", lwd=3, col=UN.GRACE.Int[,3])
tws.slope <- round(as.vector(coef(lm(UN.GRACE.Int[,2] ~ UN.GRACE.Int[,1]))[2]), 2)
tws.sdev <- round(as.vector(coef(summary(lm(UN.GRACE.Int[,2] ~ UN.GRACE.Int[,1])))[, "Std. Error"][2]), 2)
abline(lm(UN.GRACE.Int[,2] ~ UN.GRACE.Int[,1]), lwd=2.5, lty=2, col=2)
mtext(paste("Trend (cm/year): ", tws.slope, "±", tws.sdev, sep=""), cex=0.8, side=1, line=-1.1)
Any help would be appreciated - Thanks
If I understand this correctly, you want the interpolated points to show up with a different color. You can accomplish this using the type="o" option in R, which gives over-plotted lines. Here's some adjusted code that produces the following plot. I took the minor.tick command out because it must have been from a package I don't have, but otherwise it works fine (using R 2.15.3 on my local machine).
You'll notice that I just plot the item directly, rather than calling plot to NULL and then adding in lines. This simplifies the code substantially. You can play with the pch parameter in the plot call to change the symbols used, and also alter the lwd parameters as needed. In fact, you could easily give a different value to pch for the interpolated values, like you did color - it accepts a vector as an argument.
par(mar=c(4,4.5,2,2), mgp=c(2,0.6,0))
x.limit <- round(range(UN.GRACE.Int$DecimDate), 2)
plot(UN.GRACE.Int[,2] ~ UN.GRACE.Int[,1],
type="o",
pch=18,
col=UN.GRACE.Int[,3],
xlim=x.limit,
ylim=c(-20, 25),
xlab="Year",
ylab="GRACE-TWS (cm)",
axes=F)
box(lwd=1.5)
abline(h=0, col="gray50", lty=1)
axis(1, seq(2003, 2012, 1), cex.axis=0.8)
axis(2, seq(-20, 25, 5), las=1, cex.axis=0.8)
tws.slope <- round(as.vector(coef(lm(UN.GRACE.Int[,2] ~ UN.GRACE.Int[,1]))[2]), 2)
tws.sdev <- round(as.vector(coef(summary(lm(UN.GRACE.Int[,2] ~ UN.GRACE.Int[,1])))[, "Std. Error"][1]), 2)
abline(lm(UN.GRACE.Int[,2] ~ UN.GRACE.Int[,1]), lwd=2.5, lty=2, col=2)
mtext(paste("Trend (cm/year): ", tws.slope, "±", tws.sdev, sep=""), cex=0.8, side=1, line=-1.1)
You could also add the points later if you JUST want to see the points where the data was interpolated. This could be done as follows:
par(mar=c(4,4.5,2,2), mgp=c(2,0.6,0))
x.limit <- round(range(UN.GRACE.Int$DecimDate), 2)
plot(UN.GRACE.Int[,2] ~ UN.GRACE.Int[,1],
type="l",
pch=18,
col="black",
xlim=x.limit,
ylim=c(-20, 25),
xlab="Year",
ylab="GRACE-TWS (cm)",
axes=F)
box(lwd=1.5)
abline(h=0, col="gray50", lty=1)
axis(1, seq(2003, 2012, 1), cex.axis=0.8)
axis(2, seq(-20, 25, 5), las=1, cex.axis=0.8)
tws.slope <- round(as.vector(coef(lm(UN.GRACE.Int[,2] ~ UN.GRACE.Int[,1]))[2]), 2)
tws.sdev <- round(as.vector(coef(summary(lm(UN.GRACE.Int[,2] ~ UN.GRACE.Int[,1])))[, "Std. Error"][3]), 2)
abline(lm(UN.GRACE.Int[,2] ~ UN.GRACE.Int[,1]), lwd=2.5, lty=2, col=2)
mtext(paste("Trend (cm/year): ", tws.slope, "±", tws.sdev, sep=""), cex=0.8, side=1, line=-1.1)
points(x=UN.GRACE.Int[UN.GRACE.Int$Col.CSR=="red",1],
y=UN.GRACE.Int[UN.GRACE.Int$Col.CSR=="red",2],
pch=16,
col="red")
EDITED TO ADD: This is a way to color the line segments themselves by overplotting the original plot, assuming the distance to be colored is always of length one. It uses a quick'n'dirty for() loop, but it could be made into a function if you wanted.
par(mar=c(4,4.5,2,2), mgp=c(2,0.6,0))
x.limit <- round(range(UN.GRACE.Int$DecimDate), 2)
plot(UN.GRACE.Int[,2] ~ UN.GRACE.Int[,1],
type="l",
pch=18,
col="black",
xlim=x.limit,
ylim=c(-20, 25),
xlab="Year",
ylab="GRACE-TWS (cm)",
axes=F)
box(lwd=1.5)
abline(h=0, col="gray50", lty=1)
axis(1, seq(2003, 2012, 1), cex.axis=0.8)
axis(2, seq(-20, 25, 5), las=1, cex.axis=0.8)
tws.slope <- round(as.vector(coef(lm(UN.GRACE.Int[,2] ~ UN.GRACE.Int[,1]))[2]), 2)
tws.sdev <- round(as.vector(coef(summary(lm(UN.GRACE.Int[,2] ~ UN.GRACE.Int[,1])))[, "Std. Error"][5]), 2)
abline(lm(UN.GRACE.Int[,2] ~ UN.GRACE.Int[,1]), lwd=2.5, lty=2, col=2)
mtext(paste("Trend (cm/year): ", tws.slope, "±", tws.sdev, sep=""), cex=0.8, side=1, line=-1.1)
line_segs <- cbind(lstart=UN.GRACE.Int[which(UN.GRACE.Int$Col.CSR=="red")-1,c("DecimDate","CSR")],
lend=UN.GRACE.Int[which(UN.GRACE.Int$Col.CSR=="red")+1,c("DecimDate","CSR")])
for(x in 1:nrow(line_segs)) {
lines(x=c(line_segs[x,1],line_segs[x,3]),
y=c(line_segs[x,2],line_segs[x,4]),
lwd=3,
col="red")
}
I have a problem in correctly plotting the labels of the following graph:
scatterhist = function(x, y, xlab="", ylab=""){
zones=matrix(c(2,0,1,3), ncol=2, byrow=TRUE)
layout(zones, widths=c(4/5,1/5), heights=c(1/5,4/5))
xhist = hist(x, plot=F, breaks=10)
yhist = hist(y, plot=F, breaks=10)
top = max(c(xhist$counts, yhist$counts))
par(mar=c(3,3,1,1))
plot(x, y)
par(mar=c(0,3,1,1))
barplot(xhist$counts, axes=FALSE, ylim=c(0, top), space=0)
par(mar=c(3,0,1,1))
barplot(yhist$counts, axes=FALSE, xlim=c(0, top), space=0, horiz=TRUE)
par(oma=c(3,3,0,0))
mtext(xlab, side=1, line=1, outer=TRUE, adj=0,
at=.8 * (mean(x)-min(x))/(max(x)-min(x)))
mtext(ylab, side=2, line=1, outer=TRUE, adj=0,
at=.8 * (mean(y)-min(y))/(max(y)-min(y)))
}
When I type:
scatterhist(x[,6], x[,7], xlab="Cost of Taxi", ylab="Cost of Fuel")
the labels overlap with the axes values. However, if I type:
scatterhist(x[,6], x[,7], xlab="Cost of Taxi", ylab="Cost of Fuel")
scatterhist(x[,6], x[,7], xlab="Cost of Taxi", ylab="Cost of Fuel")
the second graph is correctly displayed... Can anyone help me with this issue? I have also tried to open the graph window through windows() before the first plot, but this doesn't work...
Thanks! Stefano
Your par(oma=c(3,3,0,0)) line should come before the first par(mar=...) call since it should be applied to the whole device region (i. e. you can't change the size of the outer margin if you already plotted some graphs).
scatterhist = function(x, y, xlab="", ylab=""){
zones=matrix(c(2,0,1,3), ncol=2, byrow=TRUE)
layout(zones, widths=c(4/5,1/5), heights=c(1/5,4/5))
par(oma=c(3,3,0,0))
xhist = hist(x, plot=F, breaks=10)
yhist = hist(y, plot=F, breaks=10)
top = max(c(xhist$counts, yhist$counts))
par(mar=c(3,3,1,1))
plot(x, y)
par(mar=c(0,3,1,1))
barplot(xhist$counts, axes=FALSE, ylim=c(0, top), space=0)
par(mar=c(3,0,1,1))
barplot(yhist$counts, axes=FALSE, xlim=c(0, top), space=0, horiz=TRUE)
mtext(xlab, side=1, line=1, outer=TRUE, adj=0,
at=.8 * (mean(x)-min(x))/(max(x)-min(x)))
mtext(ylab, side=2, line=1, outer=TRUE, adj=0,
at=.8 * (mean(y)-min(y))/(max(y)-min(y)))
}
I have 3 sets of data that I am trying to plot on a single plot. The first data set x values range from ~ 1 to 1700 whereas the other two data sets x values are less than 20. Therefore I want to plot them on a log axis to show variations in all the data sets. However I do not want to transform the data as I want to be able to read the values off the graph. The x axis labels I would like are 1, 10, 100 and 1000 all equally spaced. Does anyone know how to do this? I can only find examples where the data is log as well as the axis. I have attached the code I am currently using below:
Thanks in advance for any help given.
Holly
Stats_nineteen<-read.csv('C:/Users/Holly/Documents/Software Manuals/R Stuff/Stats_nineteen.csv')
attach(Stats_nineteen)
x<-Max
x1<-Min
x2<-Max
y1<-Depth
y2<-Depth
par(bg="white")
par(xlog=TRUE)
plot(x2,y1, type="n", ylim=c(555,0), log="x", axes=FALSE, ann=FALSE)
box()
axis(3, at=c(1,10,100,1000), label=c(1,10,100,1000), pos=0, cex.axis=0.6)
axis(1, at=c(1,10,100,1000), label=c(1,10,100,1000), cex.axis=0.6)
axis(2, at=c(600,550,500,450,400,350,300,250,200,150,100,50,0), label=c
(600,"",500,"",400,"",300,"",200,"",100,"",0), cex.axis=0.6)
mtext("CLAST SIZE / mm", side=3, line=1, cex=0.6, las=0, col="black")
mtext("DEPTH / m", side=2, line=2, cex=0.6, las=0, col="black")
grid(nx = NULL, ny = NULL, col = "lightgray", lty = "solid",
lwd = par("lwd"), equilogs = TRUE)
par(new=TRUE)
lines(x1,y1, col="black", lty="solid", lwd=1)
lines(x2,y2, col="black", lty="solid", lwd=1)
polygon(c(x1,rev(x2)), c(y1,rev(y2)), col="grey", border="black")
par(new=TRUE)
plot(x=Average,y=Depth, type="o",
bg="red", cex=0.5, pch=21,
col="red", lty="solid",
axes=FALSE, xlim=c(0,1670), ylim=c(555,0),
ylab = "",xlab = "")
par(new=TRUE)
plot(x=Mode,y=Depth, type="o",
bg="blue", cex=0.5, pch=21,
col="blue", lty="solid",
axes=FALSE, xlim=c(0,1670), ylim=c(555,0),
ylab = "",xlab = "")
You can do this in ggplot using scale_x_log
so something like:
myplot <- ggplot( StatsNinetee,
aes (x = myResponse,
y = myPredictor,
groups = myGroupingVariable) ) +
geom_point() +
scale_x_log()
myplot
also, avoid attach() it can give odd behavior.
I'm having the code as like below. But I'm not getting all the x axis labels and it is not displaying in 45 degree when I try to have this in pdf. Since I'm new, Please help me correct this option.
pdf(file="figure.pdf", height=3.5, width=5, onefile=TRUE)
Runtime <- c(579,0,581,610,830,828,592,651,596,596,591,581,587,594,604,606,447,434,445)
Runtime
g_range <- range(0,Runtime)
g_range
plot(Runtime, type="o", col="blue", ylim=g_range,axes=FALSE, ann=FALSE)
lab=c('2011-07-20','2011-08-03','2011-08-10','2011-08-17','2011-08-24','2011-08-25','2011-08-27','2011-08-31','2011-09-07','2011-09-10','2011-09-14','2011-09-21','2011-09-28','2011-10-05','2011-10-06','2011-10-07','2011-10-13','2011-10-19','2011-10-31')
box()
lab
axis(1, at=1:19, lab=F)
text(axTicks(1), par("usr")[3] - 2, srt=45, adj=1, labels=lab, xpd=T, cex=0.8)
axis(2, las=1, at=500*0:g_range[2])
title(main="Runtime", col.main="red", font.main=4)
title(xlab="Build", col.lab=rgb(0,0.5,0))
title(ylab="MS", col.lab=rgb(0,0.5,0))
legend(1, g_range[2], c("AveElapsedTime"), cex=0.8, col=c("blue"), pch=21, lty=1);
dev.off()
When I run your code, I do not get the image you show. The problem is this line:
text(axTicks(1), par("usr")[3] - 2, srt=45, adj=1, labels=lab, xpd=T, cex=0.8)
as axTicks(1) returns:
> axTicks(1)
[1] 5 10 15
So what is happening is that your 19 labels are being plotted at those 3 locations.
If you want to plot at the locations of the ticks (1:19) then:
text(1:19, par("usr")[3] - 2, srt=45, adj=1, labels=lab, xpd=T, cex=0.8)
will work.
Here is a full example based on your code.
Runtime <- c(579,0,581,610,830,828,592,651,596,596,591,581,587,
594,604,606,447,434,445)
g_range <- range(0,Runtime)
lab <- c('2011-07-20','2011-08-03','2011-08-10','2011-08-17','2011-08-24',
'2011-08-25','2011-08-27','2011-08-31','2011-09-07','2011-09-10',
'2011-09-14','2011-09-21','2011-09-28','2011-10-05','2011-10-06',
'2011-10-07','2011-10-13','2011-10-19','2011-10-31')
## plot
op <- par(mar = c(6,4,4,2) + 0.1) ## bigger bottom margin
plot(Runtime, type="o", col="blue", ylim=g_range, axes=FALSE, ann=FALSE)
box()
axis(1, at=1:19, lab=FALSE)
text(1:19, par("usr")[3] - 40, srt=45, adj=1.2, labels=lab, xpd=T, cex=0.7)
axis(2, las=1, at=500*0:g_range[2])
title(main="Runtime", col.main="red", font.main=4)
title(xlab="Build", col.lab=rgb(0,0.5,0), line = 4.5)
title(ylab="MS", col.lab=rgb(0,0.5,0))
legend("topright", c("AveElapsedTime"), cex=0.8, col=c("blue"), pch=21, lty=1)
## reset par
par(op)
This might be better handled using function in the gridBase package though, which allows grid and base graphics to intermingle. The reason I say it might be better is that you can specify that the y coordinate be set in terms of numbers of lines rather that trying to work out a suitable value for y in terms of the plotted data.
Here is an example:
## load gridBase
require(gridBase)
## do the base plot parts
op <- par(mar = c(6,4,4,2) + 0.1) ## bigger bottom margin
plot(1:19, Runtime, type="o", col="blue", ylim=g_range, axes=FALSE, ann=FALSE)
box()
axis(1, at=1:19, lab=FALSE)
axis(2, las=1, at=500*0:g_range[2])
title(main="Runtime", col.main="red", font.main=4)
title(xlab="Build", col.lab=rgb(0,0.5,0), line = 4.5)
title(ylab="MS", col.lab=rgb(0,0.5,0))
legend("topright", c("AveElapsedTime"), cex=0.8, col=c("blue"), pch=21, lty=1)
## at this point, DO NOT alter the dimensions of the plotting window
## now do the grid business
vps <- baseViewports()
pushViewport(vps$inner, vps$figure, vps$plot)
## this adds the text
grid.text(lab, x = unit(1:19, "native"), y = unit(-1, "lines"),
just = "right", rot = 60, gp = gpar(cex = 0.7))
## this finishes off the viewport - you have to do this or things will go wrong:
popViewport(3)
## reset par
par(op)
Note this can be a bit picky on screen, rerunning the gridBase example on my R 2.13.2 install doesn't produce any labels. Closing the device and then running the code afresh works though. I don't think this should be a problem if you are drawing to a pdf() device.