<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/svg-from-stats-software-the-good-the-bad-and-the-ugly/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://robertgrantstats.wordpress.com/2017/09/07/svg-from-stats-software-the-good-the-bad-and-the-ugly/"> R – Dataviz – Stats – Bayes</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<h3>What and why</h3>
<p>If there could only be one file format to save your charts in, it should be SVG. It stands for So Very Good (not really). But there’s good SVG and not so good SVG, and I want to explore that a little here, while also hopefully winning over some new SVG fans. I’m going to use scatterplots throughout of Ronald Fisher’s classic iris data, sepal width vs sepal length.</p>
<p>Advantage one: it’s a vector format, so you can rescale it and it doesn’t get fuzzy or pixelated. Vector graphics are a series of instructions to the computer: put a line here and a circle there, etc. Rescale it and the image is re-drawn. The alternative is raster graphics, like .png, .jpg or the old .bmp, which tells the computer that this pixel is blue and that pixel is red and so on. If you re-scale it (and of course, web browsers on other people’s computers do that all the time no matter what you tell them to do) then you get fuzz where it has to combine or interpolate pixels.</p>
<p>Advantage two: you can read it, and edit it. PDF is a vector format (although it can have embedded rasters) but isn’t human-readable. Let’s open iris_stata.pdf in a text editor:</p>
<p><img data-orig-file="https://robertgrantstats.files.wordpress.com/2017/03/screen-shot-2017-03-13-at-22-31-04.png?w=456" data-orig-size="1824,630" data-medium-file="https://robertgrantstats.files.wordpress.com/2017/03/screen-shot-2017-03-13-at-22-31-04.png?w=456?w=300" data-attachment-id="4847" data-image-meta="{" data-image-description="" src="https://robertgrantstats.files.wordpress.com/2017/03/screen-shot-2017-03-13-at-22-31-04.png?w=456" data-permalink="https://robertgrantstats.wordpress.com/2017/09/07/svg-from-stats-software-the-good-the-bad-and-the-ugly/screen-shot-2017-03-13-at-22-31-04/" data-large-file="https://robertgrantstats.files.wordpress.com/2017/03/screen-shot-2017-03-13-at-22-31-04.png?w=456?w=1024" alt="Screen Shot 2017-03-13 at 22.31.04" data-image-title="Screen Shot 2017-03-13 at 22.31.04" sizes="(max-width: 1140px) 100vw, 1140px" data-comments-opened="1" class="wp-image-4847" data-recalc-dims="1"></p>
<p>Not helpful. And now the corresponding iris-stata.svg file:</p>
<p> </p>
<p><img data-orig-file="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-08-00-34.png?w=456" data-orig-size="1488,668" data-medium-file="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-08-00-34.png?w=456?w=300" data-attachment-id="5924" data-image-meta="{" data-image-description="" src="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-08-00-34.png?w=456" data-permalink="https://robertgrantstats.wordpress.com/2017/09/07/svg-from-stats-software-the-good-the-bad-and-the-ugly/screen-shot-2017-09-06-at-08-00-34/" data-large-file="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-08-00-34.png?w=456?w=1024" alt="Screen Shot 2017-09-06 at 08.00.34" data-image-title="Screen Shot 2017-09-06 at 08.00.34" sizes="(max-width: 1140px) 100vw, 1140px" data-comments-opened="1" class="wp-image-5924" data-recalc-dims="1"></p>
<p>Mmmm, human-readable; nice.</p>
<p>This is the reason why open data activists get furious when PDFs are dumped on a webpage by a government agency claiming to have fulfilled its open data obligations. You can see immediately that SVG is plain text (which is to say, some kind of ASCII / UTF-8 / Unicode text that you can read and indeed edit), whereas PDF is squashed down to a binary format. Also, SVG can be trimmed back to the bare essentials, while PDFs are full of weird and wonderful things that are not relevant to your chart (like the ability to store bookmarks, highlight text or digitally sign forms).</p>
<h3>Making them</h3>
<p>However, you can write those SVG instructions in many ways. The nice example above came from Stata 14, but now let’s compare how different software writes out the same chart as SVG. We’ll get them all out and then delve into the SVG code. Stata first:</p>
<p><code>webuse iris, clear<br>
scatter seplen sepwid, ylabel(,nogrid) graphregion(color(white))<br>
graph export &quot;iris_stata.svg&quot;, replace<br>
graph export &quot;iris_stata.png&quot;, replace<br>
graph export &quot;iris_stata.pdf&quot;, replace</code></p>
<p>Here’s the raster png:</p>
<p><img data-orig-file="https://robertgrantstats.files.wordpress.com/2017/03/iris_stata.png" data-orig-size="1557,1132" data-medium-file="https://robertgrantstats.files.wordpress.com/2017/03/iris_stata.png?w=300" data-attachment-id="4883" data-image-meta="{" data-image-description="" src="https://robertgrantstats.files.wordpress.com/2017/03/iris_stata.png?w=385&h=280&fit=385%2C280&resize=385%2C280" data-permalink="https://robertgrantstats.wordpress.com/2017/09/07/svg-from-stats-software-the-good-the-bad-and-the-ugly/iris_stata/" data-large-file="https://robertgrantstats.files.wordpress.com/2017/03/iris_stata.png?w=1024" alt="iris_stata" data-image-title="iris_stata" sizes="(max-width: 385px) 100vw, 385px" data-comments-opened="1" class="wp-image-4883" data-recalc-dims="1"></p>
<p>Being able to export to SVG is new as of version 14, and it was undocumented! Thanks to Tim Morris for discovering it. Let’s not question how he found it. The file you get is <a rel="nofollow" href="http://www.robertgrantstats.co.uk/blog/iris_stata.svg" target="_blank">here</a>. (Then it becanme an official feature of Stata 15, out a month or two back. I’m generating output here from 14 but I’m going to come back to 15 at the end.) I invite you to open these in your text editor as well as your browser. (Browsers will display SVGs, but if you find them interesting and potentially useful, you should get a vector graphics editor too. Good options are Inkscape (free) or Adobe Illustrator (not free)).</p>
<p>Next up, R. Let’s use the built-in graphics::svg device first.</p>
<p><code>data(iris)<br>
sw&lt;-iris$Sepal.Width<br>
sl&lt;-iris$Sepal.Length<br>
svg(&quot;iris_Rsvg.svg&quot;)<br>
plot(sw,sl)<br>
dev.off()</code></p>
<p>You get <a rel="nofollow" href="http://www.robertgrantstats.co.uk/blog/iris_Rsvg.svg" target="_blank">this SVG file</a> and this PNG:</p>
<p><img data-orig-file="https://robertgrantstats.files.wordpress.com/2017/03/iris_rsvg.png?w=309&amp;h=309&amp;fit=309%2C309&amp;resize=309%2C309" data-orig-size="480,480" data-medium-file="https://robertgrantstats.files.wordpress.com/2017/03/iris_rsvg.png?w=309&amp;h=309&amp;fit=309%2C309&amp;resize=309%2C309?w=300" data-attachment-id="4896" data-image-meta="{" data-image-description="" src="https://robertgrantstats.files.wordpress.com/2017/03/iris_rsvg.png?w=309&h=309&fit=309%2C309&resize=309%2C309" data-permalink="https://robertgrantstats.wordpress.com/2017/09/07/svg-from-stats-software-the-good-the-bad-and-the-ugly/iris_rsvg/" data-large-file="https://robertgrantstats.files.wordpress.com/2017/03/iris_rsvg.png?w=309&amp;h=309&amp;fit=309%2C309&amp;resize=309%2C309?w=480" alt="iris_Rsvg" data-image-title="iris_Rsvg" sizes="(max-width: 309px) 100vw, 309px" data-comments-opened="1" class="wp-image-4896" data-recalc-dims="1"></p>
<p>But you can also install the svglite package.</p>
<p><code>data(iris)<br>
sw&lt;-iris$Sepal.Width<br>
sl&lt;-iris$Sepal.Length<br>
svglite::svglite(&quot;iris_Rsvglite.svg&quot;)<br>
plot(sw,sl)<br>
dev.off()</code></p>
<p>You might see a ‘fontconfig warning’ (I do), but it runs and you get <a rel="nofollow" href="http://www.robertgrantstats.co.uk/blog/iris_Rsvglite.svg" target="_blank">this SVG file</a>.</p>
<p>As a final option, any software that spits out PDFs can be useful after a fashion, because you could open them in Inkscape/Illustrator and then save them as SVG. So, in SPSS, we could get <a rel="nofollow" href="http://www.robertgrantstats.co.uk/blog/iris-spss.pdf" target="_blank">this PDF file</a> and this PNG:</p>
<p><img data-orig-file="https://robertgrantstats.files.wordpress.com/2017/04/iris-spss.png?w=450&amp;h=352&amp;fit=454%2C352" data-orig-size="1578,1222" data-medium-file="https://robertgrantstats.files.wordpress.com/2017/04/iris-spss.png?w=450&amp;h=352&amp;fit=454%2C352?w=300" data-attachment-id="5005" data-image-meta="{" data-image-description="" src="https://robertgrantstats.files.wordpress.com/2017/04/iris-spss.png?w=450&h=352&fit=454%2C352" data-permalink="https://robertgrantstats.wordpress.com/2017/09/07/svg-from-stats-software-the-good-the-bad-and-the-ugly/iris-spss/" data-large-file="https://robertgrantstats.files.wordpress.com/2017/04/iris-spss.png?w=450&amp;h=352&amp;fit=454%2C352?w=1024" alt="iris-spss" data-image-title="iris-spss" sizes="(max-width: 454px) 100vw, 454px" data-comments-opened="1" class="wp-image-5005" data-recalc-dims="1"></p>
<p>When you open it in Inkscape, you can save it as “Plain SVG” and get <a rel="nofollow" href="http://www.robertgrantstats.co.uk/blog/iris-spss-plainsvg.svg" target="_blank">this file</a>, or as “Inkscape SVG” and get <a rel="nofollow" href="http://www.robertgrantstats.co.uk/blog/iris-spss-inkscapesvg.svg" target="_blank">this file</a>.</p>
<p>The circle markers are represented by <em>paths</em>, when <em>circles</em> would be much more compact. Presumably Inkscape can’t tell from the PDF that they are circles and therefore a special kind of path. You could write a little program to do some simplification like this (because SVG is just a plain text file), but it would be tedious to get it right each time you fed in a different chart. Interestingly though, if you open the simple Stata SVG in Inkscape and then save it as “Inkscape SVG”, you’ll find none of that complexity afterwards, so it is in the PDF-to-SVG conversion that things get tangled up.</p>
<p>Alternatively, you could save your chart from SPSS in .eps (embedded PostScript) format, which is another old vector format. When converting from EPS, the Inkscape and plain SVGs are a bit different but not much simpler. I omit the .eps for download here because it’s just short of 1MB, but <a rel="nofollow" href="http://www.robertgrantstats.co.uk/blog/iris-spss-eps-plainsvg.svg" target="_blank">here’s the plain SVG that results</a>. The SVG file sizes vary according to complexity. Stata is smallest at 18KB, R svglite is 25KB, R svg 70KB, SPSS-Inkscape plain SVG 77KB, and SPSS-Inkscape SVG 88KB.</p>
<p>But there’s no need for that complexity; it’s just bloating added around the core components of the chart. And although none of these files are so big to trouble you, why waste space if you don’t have to? More importantly, it is squandering one of the great features of SVG if it’s no longer easily human-readable.</p>
<p> </p>
<h3><strong>Embedding fonts</strong></h3>
<p>One of the big causes of the bloat is embedding fonts. Suppose I make a chart on an Apple OS X computer and want to send it to you on a Windows one . I have Helvetica, which comes with OS X, and you don’t. I can either embed it in the SVG, which takes up more space but means that when you open the file, it will look just as I intended, or I can just stick text in there and call it Helvetica, in which case it will look right if you have paid up for that ubiquitous font, and different otherwise. It’ll probably turn into Arial. Embedding works by defining the exact shape of the characters used in the chart, then placing them where needed like a rubber stamp. I don’t know about the legal niceties of embedding a copyrighted font.</p>
<h3>Unpacking the SVG files</h3>
<p>Now let’s take a look inside.</p>
<p>Starting with the simplest, the Stata SVG, we find 184 lines of code, which is pretty slim considering there’s 150 observations to be drawn. After minimal preliminaries, it draws a <em>rect</em> for the background (what Stata calls the graphregion), then another <em>rect</em> for the background inside the axes (the plotregion). Then, if you have gridlines, they come in with one line of code for each, and then the <em>circles.</em> Then the <em>line</em> that is the y-axis, then its ticks (<em>lines</em>), labels and title (<em>text</em>), then the same for the x-axis. Essentially, all the contents from background to foreground. Here’s the snapshot again:</p>
<p><img data-orig-file="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-08-00-34.png?w=456" data-orig-size="1488,668" data-medium-file="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-08-00-34.png?w=456?w=300" data-attachment-id="5924" data-image-meta="{" data-image-description="" src="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-08-00-34.png?w=456" data-permalink="https://robertgrantstats.wordpress.com/2017/09/07/svg-from-stats-software-the-good-the-bad-and-the-ugly/screen-shot-2017-09-06-at-08-00-34/" data-large-file="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-08-00-34.png?w=456?w=1024" alt="Screen Shot 2017-09-06 at 08.00.34" data-image-title="Screen Shot 2017-09-06 at 08.00.34" sizes="(max-width: 1140px) 100vw, 1140px" data-comments-opened="1" class="wp-image-5924" data-recalc-dims="1"></p>
<p>Good features: no unnecessary wasted code, having the components of the chart appear in a consistent order, using text for labels is way better than embedding fonts (unless you really want to)</p>
<p>Bad features: no <em>id</em> or <em>class</em> info makes it hard to see what is the x-axis, for example, until you realise there’s a fixed order to the components.</p>
<p>This is what I mean by id and class: instead of just having a line for a circle that states its centre co-ordinates cx and cy, its radius r, its fill and stroke colors and strioke width, you could also add <strong>class=’datamarker’</strong> (for example) and <strong>id=’weird_outlier_3′</strong> (for example). Those don’t affect what’s drawn at all, but they function like little bookmarks to help you find your way to things of interest, and they come into their own if you want to use JavaScript to manipulate the SVG interactively (that’s another story though, too much for this post).</p>
<p>Next up is our base R output. There are some <em>symbol</em> definitions at the beginning which are the embedded characters. Scrolling to get past them takes much longer than you’d think; it feels like driving past the Googleplex. We have no idea what they are without drawing them.</p>
<p><img data-orig-file="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-12-19-56.png?w=456" data-orig-size="1586,538" data-medium-file="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-12-19-56.png?w=456?w=300" data-attachment-id="5951" data-image-meta="{" data-image-description="" src="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-12-19-56.png?w=456" data-permalink="https://robertgrantstats.wordpress.com/2017/09/07/svg-from-stats-software-the-good-the-bad-and-the-ugly/screen-shot-2017-09-06-at-12-19-56/" data-large-file="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-12-19-56.png?w=456?w=1024" alt="Screen Shot 2017-09-06 at 12.19.56" data-image-title="Screen Shot 2017-09-06 at 12.19.56" sizes="(max-width: 1140px) 100vw, 1140px" data-comments-opened="1" class="wp-image-5951" data-recalc-dims="1"></p>
<p>Then there are 150 path objects which each look like this:</p>
<p><img data-orig-file="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-13-39-27.png?w=456" data-orig-size="1504,272" data-medium-file="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-13-39-27.png?w=456?w=300" data-attachment-id="5956" data-image-meta="{" data-image-description="" src="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-13-39-27.png?w=456" data-permalink="https://robertgrantstats.wordpress.com/2017/09/07/svg-from-stats-software-the-good-the-bad-and-the-ugly/screen-shot-2017-09-06-at-13-39-27/" data-large-file="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-13-39-27.png?w=456?w=1024" alt="Screen Shot 2017-09-06 at 13.39.27" data-image-title="Screen Shot 2017-09-06 at 13.39.27" sizes="(max-width: 1140px) 100vw, 1140px" data-comments-opened="1" class="wp-image-5956" data-recalc-dims="1"></p>
<p>Those are circles. Wouldn’t it much easier, shorter and more human-readable to make them, ya know, <em>circles</em>.</p>
<p>Then there are little and big lines going from hither to yon. They are axes, ticks, and such. Each looks like this:</p>
<p><img data-orig-file="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-13-39-44.png?w=456" data-orig-size="1522,190" data-medium-file="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-13-39-44.png?w=456?w=300" data-attachment-id="5958" data-image-meta="{" data-image-description="" src="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-13-39-44.png?w=456" data-permalink="https://robertgrantstats.wordpress.com/2017/09/07/svg-from-stats-software-the-good-the-bad-and-the-ugly/screen-shot-2017-09-06-at-13-39-44/" data-large-file="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-13-39-44.png?w=456?w=1024" alt="Screen Shot 2017-09-06 at 13.39.44" data-image-title="Screen Shot 2017-09-06 at 13.39.44" sizes="(max-width: 1140px) 100vw, 1140px" data-comments-opened="1" class="wp-image-5958" data-recalc-dims="1"></p>
<p>Getting tedious. Then the text comes in, like this:</p>
<p><img data-orig-file="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-13-40-10.png?w=456" data-orig-size="1172,226" data-medium-file="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-13-40-10.png?w=456?w=300" data-attachment-id="5961" data-image-meta="{" data-image-description="" src="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-13-40-10.png?w=456" data-permalink="https://robertgrantstats.wordpress.com/2017/09/07/svg-from-stats-software-the-good-the-bad-and-the-ugly/screen-shot-2017-09-06-at-13-40-10/" data-large-file="https://robertgrantstats.files.wordpress.com/2017/09/screen-shot-2017-09-06-at-13-40-10.png?w=456?w=1024" alt="Screen Shot 2017-09-06 at 13.40.10" data-image-title="Screen Shot 2017-09-06 at 13.40.10" sizes="(max-width: 1140px) 100vw, 1140px" data-comments-opened="1" class="wp-image-5961" data-recalc-dims="1"></p>
<p>That says something like “1.0” — talk about over-thinking it.</p>
<p>The svglite version uses circles and text (hooray), but wants everything to be in its own clip-path and its own