Asked  7 Months ago    Answers:  5   Viewed   31 times

I plot a simple linear regression using R. I would like to save that image as PNG or JPEG, is it possible to do it automatically? (via code)

There are two different questions: First, I am already looking at the plot on my monitor and I would like to save it as is. Second, I have not yet generated the plot, but I would like to directly save it to disk when I execute my plotting code.

 Answers

72

There are two closely-related questions, and an answer for each.


1. An image will be generated in future in my script, how do I save it to disk?

To save a plot, you need to do the following:

  1. Open a device, using png(), bmp(), pdf() or similar
  2. Plot your model
  3. Close the device using dev.off()

Some example code for saving the plot to a png file:

fit <- lm(some ~ model)

png(filename="your/file/location/name.png")
plot(fit)
dev.off()

This is described in the (combined) help page for the graphical formats ?png, ?bmp, ?jpeg and ?tiff as well as in the separate help page for ?pdf.

Note however that the image might look different on disk to the same plot directly plotted to your screen, for example if you have resized the on-screen window.


Note that if your plot is made by either lattice or ggplot2 you have to explicitly print the plot. See this answer that explains this in more detail and also links to the R FAQ: ggplot's qplot does not execute on sourcing


2. I'm currently looking at a plot on my screen and I want to copy it 'as-is' to disk.

dev.print(pdf, 'filename.pdf')

This should copy the image perfectly, respecting any resizing you have done to the interactive window. You can, as in the first part of this answer, replace pdf with other filetypes such as png.

Tuesday, June 1, 2021
 
wavyGravy
answered 7 Months ago
70

HTML5 download attribute

Just to allow user to download the image or other file you may use the HTML5 download attribute.

Static file download

<a href="/images/image-name.jpg" download>
<!-- OR -->
<a href="/images/image-name.jpg" download="new-image-name.jpg"> 

Dynamic file download

In cases requesting image dynamically it is possible to emulate such download.

If your image is already loaded and you have the base64 source then:

function saveBase64AsFile(base64, fileName) {
    var link = document.createElement("a");

    document.body.appendChild(link); // for Firefox

    link.setAttribute("href", base64);
    link.setAttribute("download", fileName);
    link.click();
}

Otherwise if image file is downloaded as Blob you can use FileReader to convert it to Base64:

function saveBlobAsFile(blob, fileName) {
    var reader = new FileReader();

    reader.onloadend = function () {    
        var base64 = reader.result ;
        var link = document.createElement("a");

        document.body.appendChild(link); // for Firefox

        link.setAttribute("href", base64);
        link.setAttribute("download", fileName);
        link.click();
    };

    reader.readAsDataURL(blob);
}

Firefox

The anchor tag you are creating also needs to be added to the DOM in Firefox, in order to be recognized for click events (Link).

IE is not supported: Caniuse link

Wednesday, June 2, 2021
 
SheppardDigital
answered 7 Months ago
53

Do something like this:

NSBitmapImageRep *imgRep = [[image representations] objectAtIndex: 0];
NSData *data = [imgRep representationUsingType: NSPNGFileType properties: nil];
[data writeToFile: @"/path/to/file.png" atomically: NO];
Wednesday, June 2, 2021
 
ritch
answered 7 Months ago
97

Just following up on what Ian suggested: for ggplot2 you really want all the y-axis stuff in one column with another column as a factor indicating how you want to decorate it. It is easy to do this with melt. To wit:

qplot(x_value, value, 
      data = melt(dd, measure.vars=c("Predicted_value", "Actual_value")), 
      colour=variable) + facet_wrap(~State_CD)

Here's what it looks like for me: alt text
(source: princeton.edu)

To get an idea of what melt is actually doing, here's the head:

> head(melt(dd, measure.vars=c("Predicted_value", "Actual_value")))
     x_value State_CD        variable      value
1  1.2898779        A Predicted_value  1.0913712
2  0.1077710        A Predicted_value -2.2337188
3 -0.9430190        A Predicted_value  1.1409515
4  0.3698614        A Predicted_value -1.8260033
5 -0.3949606        A Predicted_value -0.3102753
6 -0.1275037        A Predicted_value -1.2945864

You see, it "melts" Predicted_value and Actual_value into one column called value and adds another column called variable letting you know what column it originally came from.

Sunday, August 8, 2021
 
michele
answered 4 Months ago
15

You could use the following code:

xyplot(from ~ posi , type="p", col="black",  data=temp, pch=16, xlim = c(0,7),
       panel = function(...){
         panel.dotplot(x = (temp$posi+1), y = temp$to, col="black", cex=1.4)
         panel.dotplot(x = temp$posi, y = temp$from, col ="black", cex=1.4)
         panel.arrows(x0 = temp$posi, y0 = temp$from, x1 = temp$posi+1, y1 = temp$to, lwd=3, col="blue", )
       }
)

yielding the following graph:

enter image description here

Please let me know whether this is what you want.

UPDATE

I posted a question concerning the problem that @skan identified and described in the comments: when a "extreme" level (like "D") is not present in temp$from then the "D" will not part of the graph, even when "D" will be needed later for temp$to. The question with answer from @Konn may be found here.

As I understand it now, we need a factor that is ordered, and we need an addition to the code specifying drop.unused.levels = FALSE in the call to xyplot. In the example we show the full set with "extremes" in "from" and as subset where the extreme "D" is absent: The full code is:

l <- c("A", "B", "C", "D")
temp <- data.frame(posi = c(1, 2, 3, 3, 2), 
                   from= factor(c("A", "B", "C", "D", "D"), levels = l, ordered = TRUE),
                   to = factor(c("C", "D", "D", "C", "A"), levels = l, ordered = TRUE)
                   ) 


xyplot(from ~ posi , type="p", col="black",  data=temp, pch=16, xlim = c(0,7), 
       drop.unused.levels = FALSE,  ## the added code
       panel = function(...){
         panel.dotplot(x = temp$posi, y = temp$from, col ="green", cex=1.6)
         panel.dotplot(x = (temp$posi+1), y = temp$to, col="black", cex=1.)
         panel.arrows(x0 = temp$posi, y0 = temp$from, x1 = temp$posi+1, y1 = temp$to, lwd=2, col="blue" )
       })

temp <- temp[1:3, ]
xyplot(from ~ posi , type="p", col="black",  data=temp, pch=16, xlim = c(0,7), 
       drop.unused.levels = FALSE,  ## the added code
       panel = function(...){
         panel.dotplot(x = temp$posi, y = temp$from, col ="green", cex=1.6)
         panel.dotplot(x = (temp$posi+1), y = temp$to, col="black", cex=1.)
         panel.arrows(x0 = temp$posi, y0 = temp$from, x1 = temp$posi+1, y1 = temp$to, lwd=2, col="blue" )
       })

yielding the following pics:

enter image description here

enter image description here

I think we have solved this question.

Friday, August 20, 2021
 
lewiguez
answered 4 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share