I am having some serious problems with layout() and it is driving me crazy when adding one figure with multiple layers.
I only seem to have a problem when adding a layer on one of the figures within the jpeg I am trying to create.
The layout is to have a 1) simple line plot on top for a time series of fish catch data and on the bottom 2) have a larger image of a map of oceanographic data layers.
I am making a series of maps using image.plot() plus contour(... add=T) and arrows my.symbols(... add=T) from library TeachingDemos.
Data is sliced from large netCDF files.
The image and contours are dissolved oxygen depth and the red arrows are surface current.
Below is my R code, data is looped through variable 'n':
jpeg(paste(interpdate[n],"DailyDOLayerCenAm.jpg", sep=""), width=1150, height=1000, res=100)
layout(matrix(c(1,2),nrow=2), heights=c(1,3))
#first plot on the top, fish catch data by time, moving each day
par(mar=c(1,4,.3,.5))
plot(Date[15:n],sail$X7.day.Average[15:n], xlim=c(Date[15],Date[350]),
xlab='',ylab='Raises/Trip',ylim=c(0,50), type='l', xaxt='n', lwd=2.5)
axis(1, Date, format(Date, "%b %d"), cex.axis = 1)
abline(18.4,0, lty=2)
points(Date[n],sail$X7.day.Average[n], pch=21, col='black', bg='red',
cex=3)
#second plot, Ocean data
par(mar=c(3,3.7,.5,1))
# layer 1 plot the main layer, interpolated grid O2 minimum depth
image.plot( as.surface( expandgrid, ww),xlim=c(xmin,xmax),
ylim=c(ymin,ymax), ylab="Latitude", xlab="Longitude",main="",
col=pal(256), legend.lab="Depth of O2 Minimum Layer (m)",
zlim=c(20,zlimit), cex=1.5)
#layer 2 add the contours
contour(as.surface( expandgrid, ww),xlim=c(xmin,xmax), ylim=c(ymin,ymax),
col='white', lwd=2, nlevels=10, labcex=1, add=T)
#layer 3 add current arrows
my.symbols(lonx,laty,ms.arrows, angle=theta, r=intensity, length=.06,
add=T,xlim=c(xmin,xmax), ylim=c(ymin,ymax), lwd=2, col="red",
fg="black")
#layer 4add the map of land/countries
plot(newmap, col="GREY", add=T)
#add a point of home port in Guatemala
points(-90.81, 13.93, pch=21, col='black', bg='yellow', cex=3.5)
dev.off()
When I plot just my ocean data, it plots fine:
https://fbcdn-sphotos-f-a.akamaihd.net/hphotos-ak-xap1/t31.0-8/10861076_10101738319375937_3436888929444896713_o.jpg
plot it within layout() I get this mess, The contour lines are fine within the x-space, but squished in y space, as are the arrows and map overlay:
https://scontent-b.xx.fbcdn.net/hphotos-xfp1/t31.0-8/10923795_10101738319625437_7583695382864373718_o.jpg
I fixed this by not using imageplot() but by using image() and adding the color legend described by Aurélien Madouasse:
https://aurelienmadouasse.wordpress.com/author/aurelienmadouasse/
I looped the images from a large arrays of oceanographic data and created a series of plots in a function.
My code (sans data) is here, from within a loop:
jpeg(paste(interpdate[n],"DailyDOLayerCenAm.jpg", sep=""), width=1150,
height=1000, res=100)
layout(matrix(c(1,2),nrow=2), heights=c(1,3))
#first plot on the top, fish catch data by time, moving each day
par(mar=c(1,4,.3,.5))
plot(Date[15:n],sail$X7.day.Average[15:n], xlim=c(Date[15],Date[350]),
xlab='',ylab='Raises/Trip',ylim=c(0,50), type='l', xaxt='n', lwd=2.5)
axis(1, Date, format(Date, "%b %d"), cex.axis = 1)
abline(18.4,0, lty=2)
points(Date[n],sail$X7.day.Average[n], pch=21, col='black', bg='red', cex=3)
#second plot, Ocean data
#plot the main layer, dissolved oxygen minimum depth
#plot the main layer, dissolved oxygen minimum depth
image( as.surface( expandgrid, ww),xlim=c(xmin,xmax),
ylim=c(ymin,ymax),ylab="Latitude", xlab="Longitude",main="", col=pal(256),
zlim=c(20,zlimit), cex=1.5)
#add the contours
contour(as.surface( expandgrid, ww),xlim=c(xmin,xmax), ylim=c(ymin,ymax),
col='white', lwd=2,levels=seq(0,zlimit,10), labcex=1, add=T)
#add sea surface current arrows
my.symbols(lonx,laty,ms.arrows, angle=theta, r=intensity, length=.06,
add=T, xlim=c(xmin,xmax), ylim=c(ymin,ymax), lwd=2, col="red", fg="white")
#add the map of land/countries
plot(newmap, col="GREY", add=T)
#add a point of home port in Guatemala
points(-90.81, 13.93, pch=21, col='black', bg='yellow', cex=3.5)
colr <- pal(256) # colors from 'blues'
legend.col(col = colr, lev = ww) # legend from Aurélien Madouasse:
mtext("Depth of O2 Minimum Layer (m)", 4, line=2.5, font=2)
dev.off()
To see a plot of my new images which I am making into a movie, see this link:
https://fbcdn-sphotos-a-a.akamaihd.net/hphotos-ak-xpa1/t31.0-8/10856647_10101738461765587_2760202217270038911_o.jpg
Related
I want to make a plot of 4 sets of data points using dual y-axis. The first two are on the left y-axis and last two are on the right y-axis. The first two belong to a set of numbers ranging from 5000 to 50,000. Second two sets of data belong range from 1-100. I want to plot it so that it is easily discernable that the two axis are not only on different scales but also the height between points from the two different sets with distinct ranges is obviously big. I don't want to be able to draw a horizontal line that would suggest some number from the left-y-axis can be mapped bijectively to some number on the right y-axis. I want to make it such that a horizontal line through any points from the left y-axis and right y-axis would belong to only one set related to either left or right axis.
How can I plot with 2 different y-axes?. There's
I'd use twoord.plot
From plotrix v3.7-5
by Jim Lemon but that has the disadvantage than base R beacause I can't add 4 sets of data into one plot. I can only use 2 sets of (x,y) pairs with 2--ord plot. I can theoretically plot n sets of (x,y) pairs using base R.
None
Here's what doesn't work:
time <- seq(0,72,12)
betagal.abs <- c(0.05,0.18,0.25,0.31,0.32,0.34,0.35)
cell.density <- c(0,1000,2000,3000,4000,5000,6000)
## add extra space to right margin of plot within frame
par(mar=c(5, 4, 4, 6) + 0.1)
## Plot first set of data and draw its axis
plot(time, betagal.abs, pch=16, axes=FALSE, ylim=c(0,1), xlab="", ylab="",
type="b",col="black", main="Mike's test data")
axis(2, ylim=c(0,1),col="black",las=1) ## las=1 makes horizontal labels
mtext("Beta Gal Absorbance",side=2,line=2.5)
box()
## Allow a second plot on the same graph
par(new=TRUE)
## Plot the second plot and put axis scale on right
plot(time, cell.density, pch=15, xlab="", ylab="", ylim=c(0,7000),
axes=FALSE, type="b", col="red")
## a little farther out (line=4) to make room for labels
mtext("Cell Density",side=4,col="red",line=4)
axis(4, ylim=c(0,7000), col="red",col.axis="red",las=1)
## Draw the time axis
axis(1,pretty(range(time),10))
mtext("Time (Hours)",side=1,col="black",line=2.5)
## Add Legend
legend("topleft",legend=c("Beta Gal","Cell Density"),
text.col=c("black","red"),pch=c(16,15),col=c("black","red"))
Not quite sure what you're after but you can add an extra 'line per plot' by using lines.
I've edited your code
## Plot first set of data and draw its axis
plot(time, betagal.abs, pch=16, axes=FALSE, ylim=c(0,1), xlab="", ylab="",
type="b",col="black", main="Mike's test data")
lines(seq(0, 1, 0.02), type = 'o')
axis(2, ylim=c(0,1),col="black",las=1) ## las=1 makes horizontal labels
mtext("Beta Gal Absorbance",side=2,line=2.5)
box()
## Allow a second plot on the same graph
par(new=TRUE)
## Plot the second plot and put axis scale on right
plot(time, cell.density, pch=15, xlab="", ylab="", ylim=c(0,7000),
axes=FALSE, type="b", col="red")
lines(seq(0, 5000, 10), type = 'o', col = 'red')
## a little farther out (line=4) to make room for labels
mtext("Cell Density",side=4,col="red",line=4)
axis(4, ylim=c(0,7000), col="red",col.axis="red",las=1)
which produces this:
Please let me know if this wasn't what you were after.
How can I move the y axis label from the left to the right of the plot area and the x-axis label from below to above the plot area in the following graph? Thanks
xleft<-c(1,2,2.5)
xright<-c(2,2.5,2.75)
ybottom<-c(1,2,2.5)
ytop<-c(2,2.5,2.75)
par(mar = c(15,15,2.75,2.75) + 0.1)
plot(c(1,3),c(1,3),type="n",main="title",xlab="xlab-move me above plot",ylab="ylab-move me right of plot",axes=F,asp=1)
axis(1,pos=1)
axis(2,pos=1)
rect(xleft,ybottom,xright,ytop,col=c("blue","red","green"))
#Label position along axes
x.label.position<-(xleft+xright)/2
y.label.position<-(ybottom+ytop)/2
#Labels
x.label<-c("Long species Name1","Long species Name2","Long species Name3")
y.label<-c("Long species Name4","Long species Name5","Long species Name5")
text(par()$usr[1]-0.5,y.label.position,y.label,xpd=TRUE,adj=1)
text(y=par()$usr[3]-0.5,x=x.label.position,x.label,xpd=TRUE,adj=1,srt=90)
par(xpd=TRUE)
legend(-0.1,0,legend=c("Species A","Species B","Species C"),fill=c("blue", "red", "green"))
Ploting axes on the right and top sides of a plot
By default R will plot the x-axis below the plot area and the y-axis to the left of it. You can change this behaviour in this way:
plot(1:100, cumsum(rnorm(100)), type="l", axes=FALSE) # Do not plot any axes
axis(3) # Draw the x-axis above the plot area
axis(4) # Draw the y-axis to the right of the plot area
box()
To also move the labels you set ann=FALSE or xlab="", ylab="" and add them afterwards with mtext, where side=1 is bottom, 2 is left, 3 is top, 4 is right. line controls the distance from the plot area.
plot(1:100, cumsum(rnorm(100)), type="l", axes=FALSE, ann=FALSE)
axis(3)
box()
mtext("Top axis", side=3, line=3)
Changing distance between labels, ticks and plot area.
Use the mgp parameter to control these details, either before the call to plot, like this
par(mgp=c(axis.title.position, axis.label.position, axis.line.position))
or in the plot command itself, like this
plot(1:100, cumsum(rnorm(100)), type="l", mgp=c(2,1,.5), las=1)
Also note the las parameter that turns all tick labels horisontal, which makes them easier to read.
I made line graphs of two different scales and i want to draw two trend lines in each line graph and display r squared value in the graph. R squared value of temperature and Year, precipitation and year. I am also having problem on showing legend on the precipitation axis. Please help me fix it.
library(lattice)
data=read.table("temp_pcp.csv",header=TRUE, sep=",")
frame=data.frame(data[1:3])
year <- data[1]
Temperature <- data[3]
Precipitation <- data[2]
gm<-data.frame(year,Temperature)
mg<-data.frame(year,Precipitation)
plot(gm, axes=FALSE, ylim=c(0,20), xlab="", ylab="",
type="l",col="black", main="Climograph")
axis(2, ylim=c(0,20),col="black",las=1)
mtext("Temperature in Degree Celcius ",side=2,line=2.5)
box()
grid()
par(new=TRUE)
plot(mg, xlab="", ylab="", ylim=c(0,60),
axes=FALSE, type="l", col="red")
mtext("Precipitation in mm",side=4,col="black",line=4)
axis(4, ylim=c(0,60), col="black",col.axis="black",las=1)
axis(1,pretty(range(year),10))
mtext("Year",side=1,col="black",line=2.5)
legend("topleft",legend=c("Tempreature","Precipitation"),
text.col=c("black","red"),col=c("black","red"))
The line graph i created is as follow;
The goal is to reproduce this Bid-Rent graph in R:
The challenge is to draw the projected circles. So far I got:
The 2D part is created by the R code below with the traditional graphic system in base R:
#Distance
X <- seq(0,7,1)
#Bid Rent Curves: Commercial, Industrial, Residential
com <- -5*X + 10
ind <- -2*X + 7
res <- -0.75*X + 4
graph <- plot(X, com, type="l", col="green", ylim=c(0,10), xlab="", ylab="", axes=FALSE)
lines(X, ind, col="red")
lines(X, res, col="blue")
abline(v=0, h=0)
segments(1,0, 1,5, lty=2)
segments(2.5,0, 2.5,2, lty=2)
title(main="Bid Rent Curves", sub="Alonso Model",
xlab="Distance from CBD", ylab="Rent per m2")
text(2.5,7.5, "Commercial", col="green")
text(3.5,4, "Industrial", col="red")
text(5.5,2, "Residential", col="blue")
(Detail: Why the curves do not respect the ylim = 0 ?)
How make the projection and draw the semi-circles?
It is not exactly a 3D plot. I have looked into plot3D and rgl. I am not sure which packages or strategy to use from here.
I'm taking you at your word that you want circles, so you need to push the plot area into the upper right corner:
outHalfCirc <- function(r,colr) {opar=par(xpd=TRUE, new=TRUE) #plot ouside plot area
polygon(x=seq(r,-r,by=-0.1),
y= -sqrt(r^2 - seq(r,-r,by=-0.1)^2) , # solve r^2 = x^2 +y^2 for y
xlim =c(0,7 ), ylim=c(0,10), col=colr, # need xlim and ylim to match base plot ranges
yaxs="i", yaxt="n", xaxs="i") # yaxis off; x and y axes meet at origin
par(opar)}
Then push plot up and to the right: This will draw a colored half-circles (largest first so they overlap) below the y=0 line.
png() # send to image file; not needed for testing
opar <- par(mar=c(15, 15, 2,2) ) # default units are in widths of text-"line".
# the margins start at lower, then clockwise
# run your code
outHalfCirc(5.5, "blue")
outHalfCirc(2.5, "red")
outHalfCirc(1, "green")
dev.off() # complete image production
par(opar) # different than the 'opar' inside the function
Voila! Although not really circles because the aspect ratio is not 1. That can be fixed (or you could set the xlim and ylim to be equal.
I'm using plotrix in R to draw NBA court features for plotting basketball shots. I'm having trouble getting the arc of the 3pt line exactly the way I want it. Using draw.arc and draw.circle allows the top of the arc to float. The top of the arc should always be at 29ft. draw.ellipse seems to solve this problem. However, when I segment the ellipse it leaves a "cross line" through the middle of the court depiction that I'd like to remove. However, I must segment the ellipse or it will extend past where it needs to. Any ideas?
Code used:
setwd("~")
library("plotrix", lib.loc="~/R/win-library/3.1")
library("RColorBrewer", lib.loc="~/R/win-library/3.1")
korver <- read.csv("Korver_XY_Test.csv", header = TRUE)
x <- (korver$x)
y <- (korver$y)
plot(x,y, cex=.7, col=brewer.pal(3, "Greens"))
#Draw 3pt Line
segments(3,0,3,14.19777, lwd=3)
segments(47,0,47,14.19777, lwd=3)
draw.ellipse(x=25, y=5.25, deg=TRUE, angle=0, arc.only= TRUE, segment=rbind(c(22,0),c(158,360)), a=23.75, b=23.75, border=1, nv=200, lwd=3)
#Draw Half Court Line
segments(0,47,50,47, lwd=4)
#Draw Court Boundaries
abline(v=0, lwd=5)
abline(v=50, lwd=5)
abline(h=94, lwd=5)
abline(h=0, lwd =5)
#draw lane
segments(17,0,17,19, lwd=3)
segments(33,0,33,19, lwd=3)
segments(19,0,19,19, lwd=3)
segments(31,0,31,19, lwd=3)
segments(17,19,33,19, lwd=3)
draw.circle(25,19,6,100,lwd=3)
#draw hoop
draw.circle(25,5.25, 0.75, 200, lwd=2)
#draw backboard
segments(22,4,28,4, lwd=4)