ggplot2 change in aspect while changing format - r

I recently tried to reproduce the Crime in Downtown Houston, Texas made by David Kahle, in order to reproduce it for another analysis later on.
Everything works well, and I can generate map as I want... However, there is an issue I cannot explain.
When I try to save the file at a larger format (let's say, 4500x1546 instead of the normal 1266x435), the size of the points, axis, title, legend etc. do not automatically adjust : they become way too small.
To illustrate this:
First image= 1200x435 (normal format), second image= 4500x1546 (adjusted format),
I observe the same effect with a geom_density plot..
I guess the solution is really trivial, but I didn't find it...

If you want to create a higher resolution png there are two approaches:
Increase the size in e.g. inches of the plot
Increase the dpi, the number of pixels per inch
You chose the second solution, this makes all the elements smaller, which is expected behavior. If you want to increase the resolution without changing the elements, increase the dpi. This can easily be done using ggsave:
g = ggplot(...)
# low res png
ggsave("lowres.png", width = 6, height = 6, dpi = 50)
# high res png
ggsave("hires.png", width = 6, height = 6, dpi = 600)
In this way there is no need to work with base_size.

Related

Trying to save a graph in R, but the file is too big. Trying to shrink it

I need to save a graph to a word document in order to submit it to a medical journal. When I paste my graph into Word, the resolution is not great and it says it's scales to 22% of the original size. When I save it using an R code, the resolution is great. However, it appears that the image is quite big when I save it. If I change the scale to 100% of the original size in word, it is way too big for the document (but is clear).
I am using the following code to save it:
jpeg("filename.jpg", units="in", width=7, height=7, res=300)
CODE FOR PLOT
dev.off()
The journal requires at least 300dpi. The issue is likely that 7x7 is just too big because when I scale it down and insert it into word, it is very clear. However, I can't scale it down to anything lower than 7x7 because it will cut off parts of my plot.
How do I fix this situation? I would like to scale down the plot so it's a smaller size, without losing any resolution and cutting off any part of the graph.
I would submit the graph as 300dpi in the size you are happy with and the journal will be able to deal with it.
However, if you want to change height etc I would do the following:
tiff("test.tiff", width = 2700, height = 1600, units = 'px', res = 300)
plot(iris$Sepal.Length, iris$Petal.Length)
dev.off()
#OR different width height
tiff("test2.tiff", width = 700, height = 1000, units = 'px', res = 300)
plot(iris$Sepal.Length, iris$Petal.Length)
dev.off()

How to save an image in R exactly as it is 'stored'?

I generated a random example plot with ggplot2 and multiple facets. I am interested in the exact positions of the individual panels and want to export the relative start and end coordinates of those panels as well as the picture of the plot (basically for point identification via mouseover events in a javascript context).
To get the information i need for the relative coordinates i use the grid package. Suppose p to be the variable which stores my plot (after p <- ggplot(...)).
With
pb <- ggplot_build(p)
pta <- ggplot_gtable(pb)
heights <- pta$heights
and analogously for the widths I get that information.
For example, in this case I get for heigths
[1] 1lines 0cm+0lines 1null
[4] 0.25lines 1null 0.25lines
[7] 1null 0.532222222222222cm 1grobheight+0.5lines
[10] 0.5lines
where the entries with unit null represent the panels. To be able to compare these I have to convert them into the same unit. null I cannot convert but the remaining ones. Using that the viewport is 1npc (npc is a unit too) in width and length I can solve an equation which allows me to create the following image (screenshot from the RStudio Plots window) with the lines drawn with grid.lines():
So everything seems to work. Now if I rescale the Plot window in RStudio the lines are drawn at the wrong places. The reason is that some units like grobheight are dependent on the current viewport. Hence, if I want to save the image (say 600 x 600 pixel) i have to do
png(fn, width = 600, height = 600)
pushViewport(viewport(width=0.5, height=0.5, xscale=c(0, 600), yscale=c(0, 600)))
print(p)
... #draw the lines
dev.off()
But.
Despite that, no matter how I save the image, say ggsave() or png() (the latter either with print(p) oder grid.draw(pta)) the actual proportions differ from the computed ones which were correct in the R environment.
A certain amount of the plotmargins seems to get cut off, and additional scaling is done apparently.
A png export looks like this for example:
The difference seems to be small, but that doesn't help. So, is there a way to save the image exactly as it is described in the gtable object pta? Is it a matter of dpi or pointsize?
Many thanks for your help,
Mika
Everything I've encountered with this exact issue stems back to the height and width call in the png() or pdf() or anything output call. Play with the height and width in order to best determine what it will look like.
If you want to know what it will look like when you export use x11(height= width= ), note the units here are "in" so you will want to mimic that in your output function.

ggplot2 grid.export plot size SVG

How can I specify the width and height of the final SVG when I do:
print(plot)
saveXML(grid.export()$svg)
I'm producing plots for a web application in SVG. I was using ggplot2 and saving the plot using ggsave which allowed me to specify size in inches for width and height. I worked great. I now needed to perform annotations on the SVG and it seemed that ggsave did not work, so I'm forced to use the grid.export approach presented above. The only aspect I seem to have control is the resolution, which allows me to make plots smaller. However, while ggsave made all the text and point size scale to a bigger size, the grid.export approach changing the resolution can make the plot smaller, but just by makes everything smaller so the plot reads worse.
For instance, setting width and height to 3
ggsave version:
grid.export version:
What I managed to do is define a new base_size on the theme to compensate the resolution scaling:
base.size = 10 * (7/size)
resolution = 72 * (size/7)
if (length(plot$theme) == 0) plot <- plot + theme_gdocs();
plot$theme$text$size = base.size
mysvg <- grid.export(res=resolution)

How to do a ridiculously wide plot

I have a long time series of 10000 observations that I want to visualize. The problem is, if I just plot it normally the time-dimension will be squished and none of the fine detail of the time-series that I want to visualize will be apparent. For example:
plot((sin(1:10000/100)+rnorm(10000)/5),type='l')
What I would like is to somehow plot the following together side by side in one gigantically long plot without using par(mfrow=c(1,100)). I then want to export this very wide plot and simply scroll across to vizualise the whole series.
plot((sin(1:10000/100)+rnorm(10000)/5)[1:100],type='l')
plot((sin(1:10000/100)+rnorm(10000)/5)[101:200],type='l')
plot((sin(1:10000/100)+rnorm(10000)/5)[201:300],type='l')
.....
Eventually I would like to have 3 or 4 of these gigantically wide plots on top of each other with a par(mfrow=c(4,1)).
I know that the answer has something to do with the pin setting in par, but I keep getting Error in plot.new() : plot region too large. I'm guessing this has something to do with the interaction of pin with the other par parameters
Bonus points are awarded if we can get the pixel height and width exactly right. It is preferable that the plot doesn't skip random pixels due to the export sizing being imperfect.
Further bonus points if the image can be encoded in a .html. and viewed this way
An alternative that you might consider is svg, which will produce something of better quality than png/jpeg in any case.
Something like
svg(width = 2000, height = 7)
par(mfrow=c(4,1), mar = c(4, 4, 0, 2))
for (i in 1:4){
plot((sin(1:10000/100)+rnorm(10000)/5),type='l',
bty = "l", xaxs = "i")
}
dev.off()
will produce a very wide plot, just over 1MB in size, which renders quite nicely in Chrome.
Note the width and height are in inches here.
P.S. svg also offers the potential for interactive graphics. Just seen a nice example allowing the user to select a region of a long time series to zoom in on, see Figure 22 in Dynamic and Interactive R Graphics for the Web: The gridSVG Package, a draft paper by Paul Murrell and Simon Potter.
It could be a Cairo-specific problem, or it could be a lack of RAM on your machine. The following code works fine for me on a Windows 7 machine with 8GB RAM.
png("wide.png", width = 1e5, height = 500)
plot((sin(1:10000/100)+rnorm(10000)/5),type='l')
dev.off()
If I change the width to 1e6 pixels, then R successfully creates the file (it took about a minute), but no image viewing software that I have available can display an image that large.
I would go on some alternative route. First of all, what exactly is the point of viewing the entire plot at hi-res? If you're searching for some sort of anomalies or irregularities, well, that's what data processing is for :-) . Think about something like finding allx > 3sigma, or doing an FFT, etc.
Next, if you really want to examine the whole thing by eye, how about writing some R-TclTK code or using dynamicGraph or iplots or zoom to produce an interactive graph that you can scroll thru "live."
ETA: IIRC RStudio has tools for interactive graph scrolling and zoom as well.

Saving plot to tiff, with high resolution for publication (in R)

A journal we are sending an article to is asking for the following:
To ensure the best reproduction quality of your figures we would appreciate high resolution files. All figures should preferably be in TIFF or EPS format... and should have the following resolution:
Graph: 800 - 1200 DPI
Photo: 400 - 800 DPI
Color (only CMYK): 300 - 400 DPI (DPI = dots per inch)
Since I am sending a graph, I am trying to save it using tiff.
Here is the code I am using:
tiff(filename = "c:\\aaa.tiff",
res = 800, pointsize = 2)
plot(1:100)
dev.off()
But sadly, it produces a very "bulky" image - and if I where to not use pointsize = 2, I would get the error message:
Error in plot.new() : figure margins too large
Any suggestions?
One thing you should do is use the compression parameter.
For instance:
tiff("outfile.tif", compression = "lzw")
LZW is a lossless compression format, so you will not lose any data, but you will definitely reduce filesize.
short answer:
It's a bulky file because the higher the resolution raster file (TIFF) then the larger the file.
The other option, EPS, is like PDF or PS. Just save in any of those. That's a vector image format and one they said was acceptable. It will be more compact and of higher quality (unless your figure contains an enormous number of points or lines.)
long answer:
One format they asked for is TIFF, a raster format. It saves the information as a value representing each pixel in the image. If the image is 100 DPI and 5" square then that's 500x500 and it saves 250000 pixels of information. As the resolution of the image gets higher and the image size stays constant then the points of information needed goes up. At 200 DPI it's 1000x1000 and 1e6 pixels of information. This explains why your file is so bulky.
In order to have a quality printed image at 5" square you would need about 300-400 DPI (dots per inch). That way you won't see each of those individual little pixels that make up the image. If it's at a lower resolution then the image is still 5" x 5" but each individual square block (pixel) that makes up the image is so large you can see them. That's why they asked for that resolution. Otherwise, text and lines in your graphs would appear blocky, jaggy, or blurry. It's why text on your computer screen (only around 100 DPI these days) isn't nearly as high quality as printed on a piece of paper (usually at least 300 dpi).
The other format they asked for was EPS. This is encapsulated postscript. Since it's a single page file PS, or postscript, would be equivalent. And, PDF is also similar. These are all vector formats, essentially the same vector format (they can contain raster format images too but let's ignore that).
A vector format file saves the information about how the image was drawn but not about each pixel. If you have an x-axis 3" long placed 0.5" from the bottom of the image then the vector file knows this description. Each feature of the graph is described in the file. Because of this, for simple drawings it is vastly more compact than any raster representation at a given image quality. Furthermore, it scales in size without losing quality. You simply ask it to draw the image at 6" x 6" instead of 5" x 5" and it scales each of the instructions for drawing the components of the image up as well. Therefore, even though the PDF or EPS file will be more compact, it will print at the highest quality.
Send a PDF or PS file and don't worry about the resolution.
When you increase resolution (res), the effective size of a plot decreases, and so the margin error jumps out. Try to make bigger picture with greater width and height (in theory, to make a plot of a same virtual size, it should be new_(width|height)=res/72*old_(width|height).
Still, as romunov suggested, it is a better idea to use ImageMagick; you won't loose quality.
I would suggest you to use devEval from the R.devices library.
I had this issue myself and solved it thanks to this :
options("devEval/args/path"=file.path(Folder_of_Output))
devEval("tiff", name="Name_output", width=120, height=800, {
barplot(data, main="imagetitle");
legend("top", legend =c("text of legend"))
})
For me it worked like a charm and the file was saved directly without issue.

Resources