I am trying to construct 3 scatter plots together using:
par(mfrow=c(3,1)),pty='s')
but they appear rather small on an A4 size paper. When I used:
par(mfrow=c(3,1)) only, the scatter plots were too stretched out (length wise). Is there anything that can be used to allow me to adjust the size so that they are large enough (3 plots) on an A4 size paper?
This is what I am currently using to plot the fist one:
(apirt$irt12[apirt$surv==1],
apirt$prtemp[apirt$surv==1],
xlab="ave.base of ears (°C)",
ylab="rectal (°C)",
xlim=c(26,42),
ylim=c(30,42),
col='blue')
Thanks,
Baz
I would suggest using par(mfrow=c(2,2), pty='s') instead. Then you will have a 2 by 2 layout of the graphs instead (with one empty quadrent), which will give more room for the square plotting regions. You should also make sure that your plotting device is set up to have the same dimensions as your paper. Reducing margins will also give you bigger plotting areas (just be sure to leave enough room for the annotations).
You should specify the size of the page, somewhere...
pdf(file="tmp.pdf",width=21/2,height=29.7/2)
op <- par(mfrow=c(3,1), pty="s") # or c(2,2)
plot(1:100,cumsum(rnorm(100)))
plot(1:100,cumsum(rnorm(100)))
plot(1:100,cumsum(rnorm(100)))
par(op)
dev.off()
Related
When using matplot() there always is a lot of empty space on the panel.
Normaly I cut it out with an external program, but it becomes a problem when arranging multiple graphs in one panel.
The option plot(x,y,...,,xaxs="i",yaxs="i") removes space around the x-axis (plot becomes wider), but not for the y-axis. I have also tried to readjust the layout matrix, giving more or less rows in the matrix to plots.
I first arrange my plots with layout() (works the same for par(mfrow=c(#,#))). Then I add the plots.
layout(rbind(
c(1,1,2,2),
c(1,1,2,2),
c(3,3,4,4),
c(3,3,4,4),
c(5,6,7,8),
c(9,10,11,12)
))
matplot(matrix(runif(100),nrow=10),type='l',xaxs="i",yaxs="i") # plot 1 upper left
matplot(matrix(runif(100),nrow=10),type='l',xaxs="i",yaxs="i") # plot 2 upper right
# fill the other panels
for(i in 3:12){
plot(1:10,runif(10),type='p',xaxs="i",yaxs="i")
}
When plotting this, a lot of the panel is wasted with empty space, while the plots are cropped. I want panel space to be filled with (nice) plots, making them as large as possible.
?par, entry mar is your friend.
with par(mar=c(bottom,left,top,right)) you can set the margins around your plot to move them closer to each other
When I try to align an image plot with a xy plot by their x-axis there is a small misalignment between the x-values. Can't figure out how to get rid of it!
Notice the misalignment of the vertical lines from the bottom plot with the x-axis on the top plot.
par(mfrow=c(2,1))
par(mar=c(0,5,5,5))
image(x=1:100,z=replicate(10, rnorm(100)))
par(mar=c(5,5,0,5))
par(xaxs="i")
plot(1:100,rnorm(100))
abline(v=1:100)
Gurus, help!! Thank you!!
PS: Could not figure it out with the post "plot-time-series-and-image-in-r-so-that-x-axis-labels-line-up-perfectly", still having issues!
The problem is that image draws data as a grid of cells which have a given width. If the length of x in image equals to nrow(z) then it specifies the midpoints of the cells. In your example this gives you rectangles centered around 1:100, effectively resulting in the x-axis covering the range from 0.5 to 100.5, which gives the observed misalignment.
In order to match the ranges in both plots you need to specify xlim to plot accordingly. In the following example I use n = 10 to make things more obvious.
par(mfrow=c(2,1))
par(mar=c(0,5,5,5))
image(x=1:n,z=replicate(10, rnorm(n)))
par(mar=c(5,5,0,5))
par(xaxs="i")
plot(1:n,rnorm(n), xlim=c(.5,n+.5))
abline(v=1:n)
Okay, so this is one of those things I had probably figured out on the past and then completely forgot about.
The trick is not only calling par(xaxs="i") but also enforcing both xlims!
par(mfrow=c(2,1))
par(mar=c(0,5,5,5))
image(x=1:100,z=replicate(10, rnorm(100)),xlim=c(0,100))
par(mar=c(5,5,0,5))
par(xaxs="i")
plot(1:100,rnorm(100),xlim=c(0,100))
abline(v=1:100)
I am trying to arrange 3 plots together. All 3 plots have the same y axis scale, but the third plot has a longer x axis than the other two. I would like to arrange the first two plots side by side in the first row and then place the third plot on the second row aligned to the right. Ideally I would like the third plot's x values to align with plot 2 for the full extent of plot 2 and then continue on below plot one. I have seen some other postings about using the layout function to reach this general configuration (Arrange plots in a layout which cannot be achieved by 'par(mfrow ='), but I haven't found anything on fine tuning the plots so that the scales match. Below is a crappy picture that should be able to get the general idea across.
I thought you could do this by using par("plt"), which returns the coordinates of the plot region as a fraction of the total figure region, to programmatically calculate how much horizontal space to allocate to the bottom plot. But even when using this method, manual adjustments are necessary. Here's what I've got for now.
First, set the plot margins to be a bit thinner than the default. Also, las=1 rotates the y-axis labels to be horizontal, and xaxs="i" (default is "r") sets automatic x-axis padding to zero. Instead, we'll set the amount of padding we want when we create the plots.
par(mar=c(3,3,0.5,0.5), las=1, xaxs="i")
Some fake data:
dat1=data.frame(x=seq(-5000,-2500,length=100), y=seq(-0.2,0.6,length=100))
dat2=data.frame(x=seq(-6000,-2500,length=100), y=seq(-0.2,0.6,length=100))
Create a layout matrix:
# Coordinates of plot region as a fraction of the total figure region
# Order c(x1, x2, y1, y2)
pdim = par("plt")
# Constant padding value for left and right ends of x-axis
pad = 0.04*diff(range(dat1$x))
# If total width of the two top plots is 2 units, then the width of the
# bottom right plot is:
p3w = diff(pdim[1:2]) * (diff(range(dat2$x)) + 2*pad)/(diff(range(dat1$x)) + 2*pad) +
2*(1-pdim[2]) + pdim[1]
# Create a layout matrix with 200 "slots"
n=200
# Adjustable parameter for fine tuning to get top and bottom plot lined up
nudge=2
# Number of slots needed for the bottom right plot
l = round(p3w/2 * n) - nudge
# Create layout matrix
layout(matrix(c(rep(1:2, each=0.5*n), rep(4:3,c(n - l, l))), nrow=2, byrow=TRUE))
Now create the graphs: The two calls to abline are just to show us whether the graphs' x-axes line up. If not, we'll change the nudge parameter and run the code again. Once we've got the layout we want, we can run all the code one final time without the calls to abline.
# Plot first two graphs
with(dat1, plot(x,y, xlim=range(dat1$x) + c(-pad,pad)))
with(dat1, plot(x,y, xlim=range(dat1$x) + c(-pad,pad)))
abline(v=-5000, xpd=TRUE, col="red")
# Lower right plot
plot(dat2, xaxt="n", xlim=range(dat2$x) + c(-pad,pad))
abline(v=-5000, xpd=TRUE, col="blue")
axis(1, at=seq(-6000,-2500,500))
Here's what we get with nudge=2. Note the plots are lined up, but this is also affected by the pixel size of the saved plot (for png files), and I adjusted the size to get the upper and lower plots exactly lined up.
I would have thought that casting all the quantities in ratios that are relative to the plot area (by using par("plt")) would have both ensured that the upper and lower plots lined up and that they would stay lined up regardless of the number of pixels in the final image. But I must be missing something about how base graphics work or perhaps I've messed up a calculation (or both). In any case, I hope this helps you get the plot layout you wanted.
I have tried to plot a series of points in R, and I use type="b" as a plot option. However, there is a lot of padding (white space) between the points and the lines between them, so much that the line disappears entirely between some points. Her is a picture of how it looks:
I have tried to make the points smaller with the cex plot option, but this does not help, as it only changes the size of the points and not where the lines between the points between these starts and ends. I do not know if this makes a difference, but the symbols I am using are pch=1.
I am interested in knowing if it is possible to reduce this padding, and how you do so. I am not interested in using type=o as a plot option instead.
Any particular reason why you don't want to use type="o"? It seems like the easiest way to get the effect you want:
# Fake data
set.seed(10)
dfs = data.frame(x=1:10, y=rnorm(10))
plot(y~x,data=dfs, type="o", pch=21, bg='white')
pch=21 is a circle marker like pch=1, but with both border and fill. We set the fill to white with bg="white" to "cover up" the lines that go through the point markers.
You can also use cex to change the marker size to avoid overlap and make the lines between nearby points visible:
set.seed(10)
dfs = data.frame(x=1:100, y=cumsum(rnorm(100)))
plot(y~x,data=dfs, type="o", pch=21, bg="white", cex=0.6)
Using a dataframe named dfs this seems to deliver a mechanism for adjusting the surrounding "white halo" to whatever size of point an halo you want by adjusting the 'cex' values of the white and black points :
plot(y~x,data=dfs, type="l")
with(dfs, points(x,y, pch=16,col="white",cex=1.4))
with(dfs, points(x,y,cex=1) )
I'm trying to create a scatter plot + linear regression line in R 3.0.3. I originally tried to create it with the following simple call to plot:
plot(hops$average.temperature, hops$percent.alpha.acids)
This created this first plot:
As you can see, the scales of the Y and X axes differ. I tried fixing this using the asp parameter, as follows:
plot(hops$average.temperature, hops$percent.alpha.acids, asp=1, xaxp=c(13,18,5))
This produced this second plot:
Unfortunately, setting asp to 1 appears to have compressed the X axis while using the same amount of space, leaving large areas of unused whitespace on either side of the data. I tried using xlim to constrain the size of the X-axis, but asp seemed to overrule it as it didn't have any effect on the plot.
plot(hops$average.temperature, hops$percent.alpha.acids, xlim=c(13,18), asp=1, xaxp=c(13,18,5))
Any suggestions as to how I could get the axes to be on the same scale without creating large amounts of whitespace?
Thanks!
One solution would be to use par parameter pty and set it to "s". See ?par:
pty
A character specifying the type of plot region to be used; "s"
generates a square plotting region and "m" generates the maximal
plotting region.
It forces the plot to be square (thus conteracting the side effect of asp).
hops <- data.frame(a=runif(100,13,18),b=runif(100,2,6))
par(pty="s")
plot(hops$a,hops$b,asp=1)
I agree with plannapus that the issue is with your plotting area. You can also fix this within the device size itself by ensuring that you plot to a square region. The example below opens a plotting device with square dimension; then the margins are also set to maintain these proportions:
Example:
n <- 20
x <- runif(n, 13, 18)
y <- runif(n, 2, 6)
png("plot.png", width=5, height=5, units="in", res=200)
par(mar=c(5,5,1,1))
plot(x, y, asp=1)
dev.off()