15

I am trying to save a ggplot2 plot in svg format. I am not using the ggsave function because the plot is generated as part of a knitr document - the device I specify for plotting is 'svg'.

The problem is that text elements from the original plot appear as paths in the svg file, at least when opened in inkscape. The source code of the svg does not look like it contains any text either.

My plotting function is defined in a separate file:

## @knitr plot_histogram
ggplot(mainFrame[complete.cases(mainFrame),]) 
+ geom_boxplot(aes(x=source, y = pPfam, fill = source)) 
+ scale_y_continuous(limits = c(0,1)) 

In the knitr document, I call the function and save the image using the 'svg' device.

```{r plot_histogram, dev = 'svg', fig.width= 7, fig.height=4, fig.show='hold', fig.path="figure/summary"}
```

So I'm not sure how to tell the 'svg' device or ggplot2 that I want to preserve text when saving svg? I would also be happy to use another graphics device if that solves the problem.

Many thanks in advance.

Yihui Xie
  • 28,913
  • 23
  • 193
  • 419
Mo Sander
  • 1,303
  • 1
  • 10
  • 14

3 Answers3

16

Neither the svg() device in base R nor the CairoSVG() device in the Cairo package supports this. All texts are turned into glyphs like

<symbol overflow="visible" id="glyph0-2">
<path style="stroke:none;" d="M 3.921875 -2.046875 L 3.921875 0.... "/>
</symbol>

I do not know why this has to be the case, and you may want to file a feature request to the r-devel mailing list. This question is not specific to ggplot2/knitr. It comes from the SVG device.

Update

The OP pointed out that the RSvgDevice actually works, and we can specify the device by:

my_svg <- function(file, width, height) {
  library(RSvgDevice)
  devSVG(file = file, width = width, height = height, bg = "white", fg = "black",
         onefile = TRUE, xmlHeader = TRUE)
}

Then in knitr code chunks, use the option dev='my_svg'.

Yihui Xie
  • 28,913
  • 23
  • 193
  • 419
  • Yihui thanks for your answer - I might try and request this from the r-devel list then because I think it would be very useful to keep the text selectable/editable. – Mo Sander Jul 11 '13 at 09:05
  • Seems there is already a device that supports text. It's called `RSvgDevice`. This links to it on [cran](http://cran.r-project.org/web/packages/RSvgDevice/) – Mo Sander Jul 11 '13 at 09:36
  • So this works with a [custom graphics device](http://yihui.name/knitr/demo/graphics/) for knitr eg. `my_svg <- function(file, width, height){ devSVG(file = file, width = width, height = height, bg = "white", fg = "black", onefile=TRUE, xmlHeader=TRUE)}` and setting `dev = 'my_svg'`. Perfect! – Mo Sander Jul 11 '13 at 10:09
  • RSvgDevice seems to be deprecated, I cannot install it in R 3.3.1 (not available for this version, though I followed http://stackoverflow.com/questions/25721884/how-should-i-deal-with-package-xxx-is-not-available-for-r-version-x-y-z-wa – TobiO Jul 02 '16 at 15:02
  • However, after updating R (since April (war R 3.2.5), it seems that it works now. Or the reason that it works now is, that I manually installed `install.packages(''gridSVG'')` although I did not load the package explicitly before reexporting just now. – TobiO Jul 02 '16 at 15:05
  • 4
    @TobiO You may install the **svglite** package and use `dev = 'svglite'` – Yihui Xie Jul 06 '16 at 15:14
  • thanks. later in the day, I found, that there were some issues, when editing the text elements in the axis labels. I will try your suggestion when I'm done writing ;-) – TobiO Jul 07 '16 at 21:07
  • Unfortunately svglite produces now output, where the textboxes stay the same size, but the text is being distorted when opening in inkscape and e.g. changing fonts or trying to type text. gridSVG works with text, but doesn't export transparency (alpha) properly – TobiO Aug 28 '18 at 04:47
  • I finally got it to work. After export with svglite open the file once in inkscape, make some spurious change and save the file Then use a text editor and remove all the lines that have the follwing format: lengthAdjust="spacingAndGlyphs" and textLength="8.00px" (use regex textLength.*\n ) Save and enjoy in inkscape – TobiO Aug 28 '18 at 05:08
  • @TobiO Update: The fix actually does work. This should be an answer. – PejoPhylo Nov 21 '18 at 15:48
1

You can also save the plots as PDF; after, convert them to SVG (optimised: for a small size; and the precision have to be bigger than 4 for good images) using the Inkscape.

0

Now ggsave("plot_using_svglite.svg",device = svglite::svglite)

renders the text correctly.

KieserS
  • 41
  • 5