<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/accelerating-ggplot2-use-a-canvas-to-speed-up-rendering-plots/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://ikashnitsky.github.io/2017/ggplot2-microbenchmark/"> Ilya Kashnitsky</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>One of the nice features of the <code>gg</code>approach to plotting is that one can save plots as R objects at any step and use later to render and/or modify. I used that feature extensively while creating maps with <code>ggplot2</code> (see my previous posts: <a rel="nofollow" href="https://ikashnitsky.github.io/2017/denmark-nuts-reconstruction/" target="_blank">one</a>, <a rel="nofollow" href="https://ikashnitsky.github.io/2017/map-hacking/" target="_blank">two</a>, <a rel="nofollow" href="https://ikashnitsky.github.io/2017/align-six-maps/" target="_blank">three</a>, <a rel="nofollow" href="https://ikashnitsky.github.io/2017/subplots-in-maps/" target="_blank">four</a>, <a rel="nofollow" href="https://ikashnitsky.github.io/2017/colorcoded-map/" target="_blank">five</a>). It is just convenient to first create a canvas with all the theme parameters appropriate for a map, and then overlay the map layer. At some point I decided to check if that workflow was computationally efficient or not. To my surprise, the usage of canvas reduces the rendering time of a ggplot quite a lot. To my further surprise, this finding holds for simple plots as well as maps.</p>
<p>Let’s start with a simple check.</p>
<div>
<pre><code># load required packages
library(tidyverse)      # data manipulation and viz
library(ggthemes)       # themes for ggplot2
library(viridis)        # the best color palette
library(rgdal)          # deal with shapefiles
library(microbenchmark) # measure the speed of executing
library(extrafont)      # nice font
myfont &lt;- &quot;Roboto Condensed&quot;
library(RColorBrewer)

# create a canvas 
canv_mt &lt;- ggplot(mtcars, aes(hp, mpg, color = cyl))+
        coord_cartesian()

# test speed with mocrobenchmark
test &lt;- microbenchmark(
        without_canvas = ggplot(mtcars, aes(hp, mpg, color = cyl))+
                coord_cartesian()+
                geom_point()
        
        ,
        
        with_canvas = canv_mt+
                geom_point()
       
        ,
        
        times = 100
)

test

autoplot(test)+
        aes(fill = expr)+
        scale_fill_viridis(discrete = T)+
        theme_bw(base_size = 15, base_family = myfont)+
        theme(legend.position = &quot;none&quot;,
              axis.text = element_text(size = 15))+
        labs(title = &quot;The speed of rendering a simple plot produced with ggplot2&quot;)
</code></pre>
</div>
<p><a rel="nofollow" href="https://i1.wp.com/ikashnitsky.github.io/images/170704/fig-01-test-simple.png?ssl=1" target="_blank"><img alt="fig1" src="https://i1.wp.com/ikashnitsky.github.io/images/170704/fig-01-test-simple.png?w=456&ssl=1" data-recalc-dims="1"></a><br>
<em>Figure 1. Microbenchmark output for a simple plot</em></p>
<p>The median time of execution is 2.7 milliseconds for the plot <em>without</em> canvas and 1.9 milliseconds for the plot <em>with</em> canvas.</p>
<p>Next, let’s do the same check for a map. For that, I will use the data prepared for <a rel="nofollow" href="https://ikashnitsky.github.io/2017/subplots-in-maps/" target="_blank">one of my earlier posts</a> and recreate the simple map that shows the division of European Union 27 into three subregions.</p>
<p><a rel="nofollow" href="https://i1.wp.com/ikashnitsky.github.io/images/170704/fig-02-sub.png?ssl=1" target="_blank"><img alt="fig2" src="https://i1.wp.com/ikashnitsky.github.io/images/170704/fig-02-sub.png?w=456&ssl=1" data-recalc-dims="1"></a><br>
<em>Figure 2. The map we use to test the rendering speed</em></p>
<div>
<pre><code># load the already prepared data
load(url(&quot;https://ikashnitsky.github.io/doc/misc/map-subplots/df-27-261-urb-rur.RData&quot;))
load(url(&quot;https://ikashnitsky.github.io/doc/misc/map-subplots/spatial-27-261.RData&quot;))

# fortify spatial objects
neib &lt;- fortify(Sneighbors)
bord &lt;- fortify(Sborders)
fort &lt;- fortify(Sn2, region = &quot;id&quot;)

# join spatial and statistical data
fort_map &lt;- left_join(df, fort, &quot;id&quot;)

# pal for the subregions
brbg3 &lt;- brewer.pal(11,&quot;BrBG&quot;)[c(8,2,11)]

# create a blank map
basemap &lt;- ggplot()+
        geom_polygon(data = neib,
                     aes(x = long, y = lat, group = group),
                     fill = &quot;grey90&quot;,color = &quot;grey90&quot;)+
        coord_equal(ylim = c(1350000,5450000), 
                    xlim = c(2500000, 6600000), 
                    expand = c(0,0))+
        theme_map(base_family = myfont)+
        theme(panel.border = element_rect(color = &quot;black&quot;,size = .5,fill = NA),
              legend.position = c(1, 1),
              legend.justification = c(1, 1),
              legend.background = element_rect(colour = NA, fill = NA),
              legend.title = element_text(size = 15),
              legend.text = element_text(size = 15))+
        labs(x = NULL, y = NULL)


# test speed with mocrobenchmark
test_map &lt;- microbenchmark(
        without_canvas = 
                ggplot()+
                geom_polygon(data = neib,
                             aes(x = long, y = lat, group = group),
                             fill = &quot;grey90&quot;,color = &quot;grey90&quot;)+
                coord_equal(ylim = c(1350000,5450000), 
                            xlim = c(2500000, 6600000), 
                            expand = c(0,0))+
                theme_map(base_family = myfont)+
                theme(panel.border = element_rect(color = &quot;black&quot;,
                                                  size = .5,fill = NA),
                      legend.position = c(1, 1),
                      legend.justification = c(1, 1),
                      legend.background = element_rect(colour = NA, fill = NA),
                      legend.title = element_text(size = 15),
                      legend.text = element_text(size = 15))+
                labs(x = NULL, y = NULL) +
                geom_polygon(data = fort_map, 
                             aes(x = long, y = lat, group = group, 
                                 fill = subregion), color = NA)+
                scale_fill_manual(values = rev(brbg3)) +
                theme(legend.position = &quot;none&quot;)
        
        ,
        
        with_canvas = 
                basemap +
                geom_polygon(data = fort_map, 
                             aes(x = long, y = lat, group = group, 
                                 fill = subregion), color = NA)+
                scale_fill_manual(values = rev(brbg3)) +
                theme(legend.position = &quot;none&quot;)
        
        ,
        
        times = 100
)
      

autoplot(test_map)+
        aes(fill = expr)+
        scale_fill_viridis(discrete = T)+
        theme_bw(base_size = 15, base_family = myfont)+
        theme(legend.position = &quot;none&quot;,
              axis.text = element_text(size = 15))+
        labs(title = &quot;The speed of rendering a map produced with ggplot2&quot;)
</code></pre>
</div>
<p><a rel="nofollow" href="https://i2.wp.com/ikashnitsky.github.io/images/170704/fig-03-test-map.png?ssl=1" target="_blank"><img alt="fig3" src="https://i2.wp.com/ikashnitsky.github.io/images/170704/fig-03-test-map.png?w=456&ssl=1" data-recalc-dims="1"></a><br>
<em>Figure 3. Microbenchmark output for a map</em></p>
<p>The median time of execution is 16 milliseconds for the map <em>without</em> canvas and 5.2 milliseconds for the map <em>with</em> canvas.</p>
<h2>Conclusion</h2>
<p><strong>Use canvas with <code>ggplot2</code></strong></p>
<h3>For the full script to reproduce the results check out this <a rel="nofollow" href="https://gist.github.com/ikashnitsky/b9c5d0b838daa2338066dbaa3e035dcc" target="_blank">gist</a>.</h3>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://ikashnitsky.github.io/2017/ggplot2-microbenchmark/"> Ilya Kashnitsky</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/LoFmz-JJmww" height="1"></a></div>