Usage of layout in R - r

I'm trying to create this layout for this plot:
layout(matrix(c(1,1,1,1,1,1,
2,2,2,3,3,3,
2,2,2,3,3,3,
2,2,2,3,3,3), nrow=4,ncol=6,byrow = TRUE))
# Set up the top chart that keeps track of the current frame/iteration
# Dress it up a little just for fun
plot(-5, xlim = c(1997,2011), ylim = c(0, .3), xlab = "", ylab = "", main = "Time",axes=F)
abline(v=1995, lwd=5, col = rgb(0, 0, 255, 255, maxColorValue=255))
# Bring back the X axis
xticks <- 1997:2011
axis(side=1, at=xticks, labels=xticks)
# Plot
plot(1:100,1:100)
plot(1:100,1:100)
Obviously the last two plot aren't plot(1:100,1:100)in my real code, but I have a question on usage of layout. Why i get this error on the first plot?
Error in plot.new() : figure margins too large
I want the first picture to have a little height

It might sound silly, but the reason is indeed that the figure margins are too large!
Let me elaborate on this. In R, there are several kind of margins to let your pictures breath:
In your particular case, the margins are eating all the space available, as you try to cram too many figures in the same plot.
To solve this, I would advise to set all the margins to 0:
par(mai=c(0,0,0,0), oma=c(0,0,0,0), mar=c(0,0,0,0))
Which will likely result in your plot to at least be rendered. At the same time, all the subplots will be way too close to each other, so you then have to increase the margins little by little, with similar calls to par(...) until the results looks fine.
Hope this helps :)

The margins are measured in multiples of line-heights via the parameters par(mar), par(oma), and par(mai), as described in this passage in ?par
MAR
A numerical vector of the form c(bottom, left, top, right) which gives the number of lines of margin to be specified on the four sides of the plot. The default is c(5, 4, 4, 2) + 0.1.
There are two solutions, you can (a) reduce the margins by setting one of the previous 'par()' settings or (b) you can increase the size of the device, either by re-sizing the device using the mouse if it's a visible device, or if you are printing to PDF, for example, you can set the device size to be larger by setting height and width parameters when you set up the device, as in:
pdf( <<FileNameHere>> , width = par('din')[1],height = par('din')[2] )
I by setting width to par('din')[1] and height to par('din')[2], you get a PDF with the same dimensions as the current device, which lets you make adjustments to the visible device with the mouse. (This is handy for one-off plots and poor practice for a production environment)
If you do reduce the margins, I recommend not setting mar=c(0,0,0,0), as that will result in not having visible axis labels.

Related

Decorana on R and using xlim

So I've been running a DCA analysis on a species/site count spreadsheet (DCA file made using Vegan and decorana command). I'm having a bit of overlap with my points, so I'm trying to extend DCA 1 axis. I keep trying to use the xlim value to narrow it down to -2,2, but it just won't do it. For some reason, it seems tied to the ylim value. If I drop the ylim to -1,1, that will force the xlim to -2,2, but I can't actually have the ylim that small.
> plot(DCA, type = "n", xlim = c(-2,2))1
First plot shows result of this command. Trying to include a ylim of (-2,2) didn't change it either. Second plot shows result of this command:
> plot(DCA, type = "n", xlim = c(-2,2)), ylim = c(-2,2)2
I'm not exactly an expert at this, and I feel like I might be making a stupid mistake. Anyone got any ideas?
The plot is enforcing equal aspect ratio, and if you insist on having full range on y-axis (you do not set ylim), the x-axis will be set to accommodate the range you want to show on y-axis. You must either change the shape of your graphics display for a shorter x-axis, or then you also must set the range on y-axis with ylim Your choice. If you draw on square graphics window, the output will be square and it will be taken care that both the x and y scale (xlim, ylim) will fit the square. Changing the shape of the graphics window or setting both limits will help. Function locator() can be used to query coordinates in an existing plot, and these can be used to set up the new limits.
It is better to start again from a clean table. My intention was not to be rude, but trying to complement the answer in comments leads into terse messages where details and special cases are hard to handle. So I try to explain here how you can control the display and the axis limits in vegan ordination graphics. This answer has two main parts: (1) why we insist on equal aspect ratio, and (2) how to survive with equal aspect ratio. The latter can indeed be tricky, but we have not made it tricky because we are evil, but it is necessarily tricky.
First about the equal aspect ratio. This means that the numeric scales is equal on vertical (y) and horizontal (x) axes. In ordination the "importance" of an axis is normally reflected by its length: important axes are long, minor axes are short. In eigenvector methods this is determined by eigenvalues (which actually define the scatter of points along axes). In DCA (decorana) it should be the SD scaling so that one unit is equal to average width of species responses. We pay great attention in scaling axes accordingly, and we want to show this in the plot so that long x axis remains long and short y axis remains short even when the graph is designed for a portrait printer page shape. In this way the axis scaling (tic values) are equally spaced on both axes, and distances in the graph are equal horizontally, vertically or diagonally. Also if you draw a circle in the plot, it will remain a circle and not flattened or elongated to an ellipse. So this is something that we insist as a necessary feature of an ordination graph.
Insistence on equal scaling of equal axes comes with a price. One obvious price is that the ordination plot may not fill the graph area, but there can be a plenty of empty space in the graph for shorter axes. You can get rid of this adjusting graph shape – typically making it flatter. Another price that must be paid is the one that bit you: setting axis limits is tricky. However, this is not a vegan invention, but we use base R plot command with option asp = 1 for equal aspect ratio of axes.
To see how we can set axis limits with equal ratio, let us generate a regular rectangular grid and plot it:
x <- seq(-2, 2, by=0.2)
xy <- expand.grid(x, x)
plot(xy, asp=1)
This is a square grid on a square plot and nothing very special. However, if we plot the same grid on rectangle the aspect ratio remains equal, numeric scales are equal and the points remain equidistant on a square, but there is a lot of empty space and x-axis has longer numeric scale (but the points have unchanged numeric scale). If we try reduce only the x-scale, we face a disappointment:
plot(xy, asp=1, xlim=c(-1,1), main="xlim=c(-1,1)")
The graph is essentially similar as the first unlimited case with unchanged x. Setting xlim does not remove any points, but it only tells plot that do not reserve space but for that range on x-axis. However, y-scale is still longer and with equal aspect ratio it will also set the scale for x-axis and since there is empty space in the graph, the points are plotted there (this is analogous to having empty space even when there is nothing to plot there). To really limit the x-axis, you must simultaneously limit the y-axis accordingly:
plot(xy, asp=1, xlim=c(-1,1), ylim=c(-1,1), main="xlim=c(-1,1), ylim=c(-1,1)")
This give the desired x-limits .
Like I wrote, we did not invent that nastiness, but this is base R plot(..., asp=1) behaviour. I know this can be tricky (I have used that myself and sometimes I get irritated). I have been thinking could we be more user-friendly and by-pass base R. It is pretty easy to do this in a way that works in many normal use cases, but it is much harder to do this so that it works in most cases, and I don't know how to do this in all possible cases. If anybody knows, pull requests are welcome in vegan.
Finally, there is one tool that may help: vegan has an interactive dynamic plotting tool orditkplot where you can zoom into a plot by selecting a rectangle with left mouse button. However, this function may not work in all R systems, but if it works it gives an easy way of studying details of the plot (but if you have Mac with one-button mouse, don't ask me how it works: I don't know). You can start this with
orditkplot(mod, display="sites") # or "species", but only one
Even without orditkplot you can use base R function locator(): click the diagonally opposite corners of the rectangle you want to focus on, and this give you the xlim and ylim you need to set to zoom into this rectangle.

space images in PDF using R

I'm using R to generate PDFs that contain QR code images. The images have to be arranged in a 4x6 pattern like this mockup that i made in Word:
I've written a loader that i plan to write into a loop later on (i've got over 2000 images). However, i can't quite get the spacing right. This is my current result:
It's not a bad thing that the images are smaller, but the large margins on top and bottom and right are a problem. I've been trying to set par(mar = c(4,0,0,0) in the loop to see if the images would get a bottom margin, but that doesn't happen. Also, i think i need to use padding instead of margin, but i haven't found a parameter for padding.
Is there a way to do this? The code i've written so far:
# import libraries
library(qrcode)
library(imager)
# clear workspace
rm(list = ls())
filenames <- list.files(path = "./QR/2/")
im <- load.image(paste0("./QR/2/",filenames[1]))
im <- list()
for(i in 1:24){
im[[i]] <- load.image(paste0("./QR/2/",filenames[i]))
}
pdf("./QR/2/stickervellen/1.pdf", paper = "a4")
par(mfrow = c(6,4), mar=c(0,0,0,0))
for(i in 1:24){
par(mar = c(4,0,0,0))
plot(im[[i]], axes = F)
}
dev.off()
the images i'm using can be found here: https://easyupload.io/v4gmbf
You have to specify the size of your graphics region with width and height. If you don't do that, default values (7 inch) are used and for an A4 paper which has a height of 11.7 inch you won't get full coverage.
pdf("./QR/2/stickervellen/1.pdf", paper="a4", width=8.3, height=11.7)
par(mfrow=c(6, 4), mar=rep(0, 4))
for(i in 1:24){
plot(im[[i]], axes=F)
box()
}
dev.off()
Please note that I added box() in your code so that the extent of the individual plots and the margins around them are visible.
In ?pdf you may also find that if you specify the paper argument
if either width or height is less than 0.1 or too large to give a total margin of 0.5 inch, it is reset to the corresponding paper dimension minus 0.5.
That's why there will always be a small margin around the whole page when you specify paper. If you don't want that margin, just leave out paper="a4" and you will get this:

R partykit::ctree offset labels on edges

I am working with ctree and my data set has a covariate of factors that create a node. There are enough factors for that covariate and their names are long enough that they overlap on each other in the edges created at the node. I want to find a way to stop this overlap.
I checked other questions and found one answer that supplies some help. The plot for ctree relies on the grid package and I can use functions to write new labels on the edge. My problem now is that I don't know how to suppress the labels that are printed as default when I plot the tree. I don't know enough about grid or plot.party to figure out which object needs to be suppressed.
An example of my problem in the following image:
Code for my example problem:
libary(partykit)
library(tidyverse) #this is here for the mpg data set in next line. not required for partykit
data(mpg)
irt <- ctree(hwy~as.factor(class),data=mpg)
plot(irt)
The resulting 1st node has one edge with "2seater, compact, midsize, subcompact" and the other edge with "minivan, pickup, suv". What I end up seeing in the plot is "2seater, compact, midsize, subcompaminivan, pickup, sub". I've already made the graphics device full screen. (I have other trees that only have one node and so that makes those look odd at the full screen dimension, so I don't want to go back and forth.)
The partial solution I have is
plot(irt, pop=FALSE)
seekViewport("edge1-1")
grid.text("2seater, compact,\n midsize, subcompact")
This stacks "2seater, compact" on top of "midsize, subcompact" and would keep them from overlapping "minivan, pickup, suv". But now, I have the original too-long label still in the plot. And the edge that the label I'm trying fix is attached to has a break in a place that doesn't work with the new stacked label. It would be nice to fix that edge, but the real problem is suppressing the original, too-long label on edge1-1.
The edge labels are drawn by the function edge_simple() which offers various kinds of justifications for the edge labels, see ?edge_simple. The justification is only applied if the edge labels are on average longer than justmin, defaulting to Inf (i.e.: no justification). Various justifications are possible (alternating, increasing, decreasing, or equal).
Thus, in your case the simplest solution is probably to set justmin to a small enough finite value. Alternatively (or additionally) you could also decrease the font size by setting gpar(fontsize = ...). For illustration both examples below have been generated on a 6in x 8in PNG device:
library("partykit")
data("mpg", package = "ggplot2")
irt <- ctree(hwy ~ factor(class), data = mpg)
plot(irt, ep_args = list(justmin = 15))
plot(irt, ep_args = list(justmin = 15), gp = gpar(fontsize = 10))

change the font size and margin of R graph

I am experimenting with the investigate_var_importance in package of bartMachine
investigate_var_importance(bart_machine_cv, num_replicates_for_avg = 20)
It turns out that the generated graph is so big, especially the text label along with the x-axis. The default [R Graphics: Device 2(Active) cannot even hold the whole picture. How to change the font size and margin of this plot?
margin can be set by par(mar=c(bottomMargin, left, up, right))
see par to set that parameter
c(0,0,0,0) will not leave any space. You might not want this, as there wouldn't be any space for the axis.
par(oma=c(bottomMargin, left, up, right))
sets the outer margins of the plot
if you send the plot to a pdf, you can increase the size of the plot, which will be able to hold the whole plot i.e,
pdf('nameOfplot.pdf', 20, 6) ## opens a device, and produces a file much wider than longer
plot whater you want
dev.off() ## closes the device you have opened with pdf
if you play with those parameters you might be able to fit your plot

How can I return to previous frame in R?

I'm doing a plot in R using a simple layout:
layout(matrix(c(1,2),1,2))
After I have drawn the two sides of the plot, I need to return to the first to draw two more lines (that span to the other side, and only after drawing the second side I will know the right coordinates).
I know I can use frame() to move between frames, but it only goes forward, and when it returns to the beginning, it clears the whole drawing. Is it possible to move a frame back?
Despite the warnings you can use par(mfg=...) to control the focus of plotting when using layout:
layout(matrix(1:4,2,2));
plot(1:10, 1:10);
plot(10:1, 1:10);
par(mfg=c(1,1));
abline(h=5)
I would not have expected dev.set(dev.prev()) to work since I think it's all being written to the same device.
IRTFM is correct, but if the different graphs in the layout have different scaling, then you may have to reset the scale after changing the target frame for new graphical elements added to the previous frame to be scaled correctly.
Modifying IRTFM's example a bit to demonstrate, note that this code does not produce the expected result of a horizontal line in the first graph at a value of 5 due to inconsistent scaling.
layout(matrix(1:4,2,2))
plot(1:10, 1:10)
plot(12:1, 1:12)
par(mfg=c(1,1))
abline(h=5)
However, the following code produces the expected result of a horizontal line in the first graph at a value of 5 due to resetting the appropriate scale before adding the abline element.
layout(matrix(1:4,2,2))
plot(1:10, 1:10)
plot(12:1, 1:12)
par(mfg=c(1,1))
plot.window(xlim = c(1, 10), ylim = c(1, 10))
abline(h=5)
Changing to an arbitrary frame in a layout is possible with the "mfg" graphics parameter, but you will need to reset the window scaling for any added elements to appear on the same scale as previously established. Same goes for use of mfrow or mfcol graphics parameters to create multipanel graphs.

Resources