8

Every graph that I make in plotly looks great up until the moment I save it, so the image looks kind of matte, if it makes sense, just really bad quality. Does anyone know how to save it in high quality? You can use this basic chart as an example.

library(plotly)

x <- c(1:100)
random_y <- rnorm(100, mean = 0)
data <- data.frame(x, random_y)

p <- plot_ly(data, x = ~x, y = ~random_y, type = 'scatter', mode = 'lines')

Thank you!

LauraP
  • 311
  • 1
  • 4
  • 13

4 Answers4

7

At least in Plotly v4.7.1+ you can export the graph as SVG (since being a vector graphic format this is pretty much highest quality possible).

To do so you need to have the package Rselenium installed. Then you can use Plotly's export function as follows (in this example using Chrome as Selenium driver):

if ( !require(RSelenium) ) {
  install.packages("RSelenium", repos = "https://cloud.r-project.org/")
}

p %>%
  export(file = "filename.svg",
         selenium = RSelenium::rsDriver(browser = "chrome"))

This will download the chart as filename.svg to your default download directory (~/Downloads on many Linux distros or %USERPROFILE%\Downloads on Windows). If you want to download the SVG to the current R working directory instead, you need to pass several options to the Selenium driver (Chrome in this example):

p %>%
  export(file = "filename.svg",
         selenium = RSelenium::rsDriver(browser = "chrome",
                                        extraCapabilities = list(
                                          chromeOptions = 
                                            list(prefs = list(
                                              "profile.default_content_settings.popups" = 0L,
                                              "download.prompt_for_download" = FALSE,
                                              "download.default_directory" = getwd())
                                            ))))

A more sophisticated custom export function which allows to set the width and height of the exported SVG (and much more incl. optional conversion to PDF and PNG) can be found in this Gist: https://gist.github.com/salim-b/32c4370cee4ac0a3fbfef13a9ce98458

Salim B
  • 2,409
  • 21
  • 32
  • Hey salim, curious to try your more advanced code. Would it work inside an r shiny app? And secondly, is it installable as a package or do I just need to copy the whole code – Mark Apr 18 '18 at 07:22
  • Hi Mark, 1) I've no experience with shiny so far, so I can't tell. If you wanna run the code on a shiny server, you would at least need to ensure that the development package of `librsvg` for PNG/PDF conversion is available. I have no clue if Selenium would work as supposed. I'd say: Just try :) 2) No, it's not installable as a package (yet). It's on my to-do list to build a package containing all my Plotly helper functions, but I couldn't find the time so far... – Salim B Apr 19 '18 at 09:03
  • does this require a paid subscription to plotly? as on chart studio it does for formats like pdf, eps and svg? – Eular Jun 22 '19 at 17:36
  • > does this require a paid subscription to plotly? Nope. Today there's also a [dedicated Electron app](https://github.com/plotly/orca) to create static images of Plotly graphs. You can use the [`plotly::orca()` function](https://github.com/ropensci/plotly/blob/master/R/orca.R). If you still prefer to use Rselenium for any reason, note that it's advisable to also [specify the correct `chromever`](https://stackoverflow.com/questions/55201226/session-not-created-this-version-of-chromedriver-only-supports-chrome-version-7/56173984#56173984) to avoid running into an error from time to time. – Salim B Jun 23 '19 at 02:03
1

The answer provided by @Peter Gaultney produced an error for my box plot.

These two methods might work in more circumstances and improve the image quality using htmlwidgets::onRender().

Option 1. As @chinsoon12 suggests, save as SVG. This code will open a web browser then make the browser download the image. Note that setting the viewer to null will stop the RStudio viewer pane from working, so you'll need to save it, save the plot image, and then restore it.

library(htmlwidgets)

# Save viewer settings (e.g. RStudio viewer pane)
op <- options()

# Set viewer to web browser
options(viewer = NULL)

# Use web browser to save image
p %>% htmlwidgets::onRender(
  "function(el, x) {
  var gd = document.getElementById(el.id); 
  Plotly.downloadImage(gd, {format: 'svg', width: 600, height: 800, filename: 'plot'});
  }"
 )

# Restore viewer to old setting (e.g. RStudio)
options(viewer = op$viewer)

Option 2. You can save as PNG and specify a higher resolution. You should probably increase the line thickness, fonts, etc. for this method.

library(htmlwidgets)

# Save viewer settings (e.g. RStudio viewer pane)
op <- options()

# Set viewer to web browser
options(viewer = NULL)

# Use web browser to save image
p %>% htmlwidgets::onRender(
  "function(el, x) {
  var gd = document.getElementById(el.id); 
  Plotly.downloadImage(gd, {format: 'png', width: 1200, height: 1600, filename: 'plot'});
  }"
 )

# Restore viewer to old setting (e.g. RStudio)
options(viewer = op$viewer)
Kayle Sawyer
  • 549
  • 7
  • 22
  • I assume option one saves it immediately on render? Would you know how to do this through a button in r shiny on an app that has several plots ? – Mark Apr 11 '18 at 07:05
  • Sorry, I don't know R shiny. I use this code for plotly in offline mode, and I don't know how to save the SVG in an online app. Ask another question with a link to this one. – Kayle Sawyer Apr 12 '18 at 12:14
0

If, like me, you're trying to use Plotly in Offline mode, I recommend the following procedure:

First, save as SVG:

fname = "/home/me/output"
plot(fig, filename=fname, image='svg', image_filename=fname)

Then open the HTML (named output.html) in your browser, and it will prompt you to save the SVG (this is a frustrating step, but there's currently no way around it with Plotly).

Then, use cairosvg to convert the SVG to PNG using better scaling. See my other answer here. Can I specify scaling when using the cairosvg module inside of python

Peter Gaultney
  • 3,269
  • 4
  • 16
  • 20
0

If you dive down into the plotly js library, you'll find a "scale" parameter, which is easy enough to use. The following would produce a 1200 x 1600 png.

Plotly.downloadImage(gd, {scale: 2, width: 600, height: 800})
Thinkable
  • 301
  • 2
  • 7