How to delete the last page from grid/grDevices? - r

Is there a method to delete the last page created with the grid.newpage() or revert the graphic device to the state before the last plot was added?
Background:
I wrote a function that adds a layer (eg. geom_label) to an existing ggplot with location of data points based on the absolute plot dimensions (eg. inches/lines), rather than data range.
The procedure is: produce a plot, print it on the current device, measure the printed grobs and enhance the data frame to be plotted with relevant statistics (eg. origin of the coordinate system per panel, relative units per inch or per line), create the new plot with an additional layer with aesthetics computed with these new variables, print this final plot.
The main purpose was to have a tool that nicely aligns additional text/labels with summary statistics within the plotting area, even when facets or grouping variables are in use.
The issue is that an unnecessary page is produced with the plot I do not really use, except for making measurements, and I did not find any grid or grDevices method to delete the last printed page. Do you know of any such function?
There are some potential flawed workarounds: printing new ggplot object without calling grid.newpage() (but you no longer simply print(plot)), or plotting the first plot in a temporary device with same parameters as the target device (but it's not universal, and requires different approach per device; eg. solutions for .png and multipade .PDF will differ).

Grid units already let you place objects at fixed positions in the panel,
library(ggplot2)
library(grid)
ag <- grobTree(textGrob('+', x = unit(3,"cm"), y=unit(1,'npc') - unit(1,'in')))
qplot(1:10,1:10) +
annotation_custom(ag)

Related

Resize plot canvas to actual plot size in R with ggplot2

One of the features of the R plotting machinery that I use more often is png(file=..., width=..., height=..., res=...).
Normally, I set precise values within the function, e.g. png("out.png", height=1500, width=2500, res=250).
I am now making a tool that makes an automatic plot from the provided dataset, but the tool is agnostic in respect to the number of rows it has to show in the plot, i.e. it plots what it receives. Sometimes, the plot has a large white area around it. Some other times, the canvas is too small and some rows fall outside.
I'm trying to fix this by calculating height and width according to the number of rows in the dataframe, but I find this approach error prone and suboptimal.
For example, inkscape has a nice function called "Resize page to drawing or selection" which will resize the canvas to match the boundaries of the plot. You can even pass a certain tolerance value so that your plot will still have some white around it.
Does R have this possibility, perhaps within ggsave() if not within png()?

r - how to set plot size regardless of legend width ggplot2

I'm looping through a spatial feature dataframe and creating hundreds of maps from each column using ggplot2. Depending on the data present in the column, the legend for each map may be a different size, making the plot size different for each map. Although subtle, you can see below that the first map is offset to the left relative to the second map because of the longer label in the legend
I'd like to maintain the size of the plot area (in this case, the map area) so that all the saved maps are consistently sized and lined up when flipping through them. I've looked through questions and answers on here, but all I've been able to find are solutions for how to preserve aspect/ratio of different plots on the same image/document as described here. I'd like to be able to save each map as its own file.
Can anyone give me suggestions about how to keep the plot size consistent regardless of legend width when saving these plots as images using ggplot2?

add data points to existing plot in R

I try to receive the data from a sensor from time to time and plot it in real time. That means the length of the dataset is not know before hand. And need to adjust the range of the graph dynamically.
I tried the following
plot(1,10, xlim=range(0,10), ylim=range(0,10), type='n')
points(1,data[1])
points(2,data[2])
But once the number of dots is beyond the range of x axis (10 in this case), the data points are out of the range. How to adjust the range accordingly?
Just issue a new plot command with an expanded range. On modern computers the time taken to recreate the plot is small and you generally will not see a delay. Any other approach will essentially do the same thing, clear the current plot and create a new plot.
The ggplot2 and lattice packages have ways of constructing a plot and updating the plot, but when the updated plot is shown it is redrawn from scratch.
There is a zoomplot function in the TeachingDemos package which will allow you to change the range of a plot, but it also will just redraw the plot from scratch (and due to changes in R 3.0.0 it is not currently working, so if you wanted to use it you would need to go back to R 2.15 or before, or wait for it to be fixed).
You can't adjust the range dynamically (sometimes Excel is better). However, you can keep track of what you've plotted, and redo the plot when you've reached the limit. You could also just make a new plot every time you get more data, which would be a way of faking a dynamic update.

Toggling amongst plot spaces

Scenario: Five Graphs for Five Periods {3M, 6M, 1Y, 2Y & 3Y}, each with their own (1-2) scatter plots; sharing the same y-range (values).
Each period has different x-ranges and labeling policies.
For example, one could have either a fix or location policy; another none.
The X-Range appears to be immutable/plot-space. So I'm thinking of creating parallel plot spaces with their particular xRanges & labeling policies.
I studied the relationship of a plot space with the x.axis(s) & plot(s):
Graph <=== {NSMutableArray *plotSpaces}
x.axis/plot-space.
plot/plot-space
So I believe I can:
1) Create a plotspace.
2) Assign the plotspace to a particular plot, x-axis & xRange.
3) add or remove the plot to/from the graph.
4) Redraw the graph.
So when the user selects a period/plotspace, All I need to do is: replace any existing plots with the period plot(s) which will cause the graph to plot the plots & display the respective x-axis (Y-axis is common)?
[myGraph removePlot:(CPTPlot *)oldPlot];
[myGraph addPlot:(CPTPlot *)plot toPlotSpace:(CPTPlotSpace *)space];
...I'm a little lost here.
?
Axes are also assigned to a plot space. You would need to swap out the axes, too. You'll take a relatively large performance hit by adding and removing plots and axes all the time.
As you observed, the plot ranges are immutable. That just means that you can't change an existing range, not that you can't set a new one. Either create a new CPTPlotRange object or make a mutable copy of an existing one.
Whenever you want to change the plot scale, you need to do the following things. These can all change in place, without removing and replacing major pieces of the graph.
Change the plot ranges as described above.
Update the labeling policy and related properties of the axis.
Call -reloadData on the plot to load the new data.

Repeat plot command with minor changes in R

I made a plot in R and I want to repeat all the commands (like plot(), legend() or line()) that were carried out for this plot, with some minor changes. For example I want to set the axes to logarithmic scale and change the title of the plot.
In gnuplot I would use the replot command.
plot ...
set title "The same plot with logarithmic axes"
set logscale
replot
Is something like this possible in R. The only thing that comes to my mind of doing this (besides changing the values manually and re-run the lines of codes) would be setting up a function, that asks for all parameters that might be changed by the user.
Thanks for your help,
Sven
R uses a pen and paper graphics model - once the plot has been drawn on the device that is it. If you want to change some aspect of the plot, you need to replay the graphics function calls that produce the plot with the changes made to the code.
Depending on what you are really doing there are two options:
If this is just for you, write code in a text editor / IDE that knows R and can send chunks of code at a time to R. That way the code to produce the figure is recorded in a separate script which you can paste into/send to R making the changes you need each time to the script.
If you are going to be doing this often, then write yourself a wrapper plotting function that encapsulates the plot code you want but allows you to pass in arguments to alter the aspects you want.
Lattice and ggplot2 are a little different as they are based on grid graphics and create objects that when printed produce a plot on the device. One can manipulate that object to alter what is drawn, and with grid one can push and pop things on to / off a viewport.

Resources