<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/creating-slopegraphs-with-r/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://datascienceplus.com/creating-slopegraphs-with-r/"> R Programming – DataScience+</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>Presenting data results in the most informative and compelling manner is part of the role of the data scientist. It's all well and good to master the arcana of some algorithm, to manipulate and master the numbers and bend them to your will to produce a “solution” that is both accurate and useful. But, those activities are typically in pursuit of informing some decision or at least providing information that serves a purpose. So taking those results and making them compelling and understandable by your audience is part of your job!</p>
<p>This article will focus on my efforts to develop an R function that is designed to automate the process of producing a <a rel="nofollow" href="https://www.edwardtufte.com/bboard/q-and-a-fetch-msg?msg_id=0003nk" target="_blank">Tufte style slopegraph</a> using <code>ggplot2</code> and <code>dplyr</code>. <a rel="nofollow" href="https://en.wikipedia.org/wiki/Edward_Tufte" target="_blank">Tufte</a> is often considered one of the pioneers of data visualization and you are likely to have been influenced techniques he championed such as the <a rel="nofollow" href="https://en.wikipedia.org/wiki/Sparkline" target="_blank">sparkline</a>. I've been aware of slopegraphs for quite some time as an excellent visualization technique for some situations. So when I saw the <a rel="nofollow" href="https://ekonometrics.blogspot.com/2018/05/edward-tuftes-slopegraphs-and-political.html" target="_blank">article</a> from Murtaza Haider titled “Edward Tufte’s Slopegraphs and political fortunes in Ontario” I just had to take a shot at writing a function.</p>
<p>To make it a little easier to get started with the function I have taken the liberty of providing a couple of small datasets for you to practice with, please see <code>?newcancer</code> and <code>?newgdp</code>.</p>
<h2>Installation and setup</h2>
<p>Long term I'll try and ensure the version on <code>CRAN</code> is well maintained but for now you're better served by grabbing the current version from GITHUB today since I tend to put all the latest features and fixes there in between pushing to <code>CRAN</code>. I've provided the instructions for installing both commented out below.</p>
<pre><code>knitr::opts_chunk$set(
  collapse = TRUE,
  comment = &quot;#>&quot;
)
# Install from CRAN
# install.packages(&quot;CGPfunctions&quot;)

# Or the development version from GitHub
# install.packages(&quot;devtools&quot;)
# devtools::install_github(&quot;ibecav/CGPfunctions&quot;)
library(CGPfunctions)
</code></pre>
<h2>Simple examples</h2>
<p>If you're unfamiliar with slopegraphs or just want to see what the display is all about the dataset I've provided can get you started in one line</p>
<pre><code>newggslopegraph(newcancer, Year, Survival, Type)
</code></pre>
<p>Gives this plot:<br>
<a rel="nofollow" href="https://i2.wp.com/datascienceplus.com/wp-content/uploads/2018/06/ggslope1-1.png?ssl=1" target="_blank"><img sizes="(max-width: 392px) 100vw, 392px" src="https://i0.wp.com/datascienceplus.com/wp-content/uploads/2018/06/ggslope1-1-392x490.png?resize=392%2C490&ssl=1" alt="" width="392" class="wp-image-14371" data-recalc-dims="1" height="490"></a></p>
<p>Slopegraphs are designed to provide maximum information with “minimum ink”. Some key features are:</p>
<ul>
<li> Scaling – this function plots to scale; a big gap indicates a big difference.</li>
<li> Names of the items on both the left-hand and right-hand axes are aligned, to make vertical scanning of the items’ names easier. Rank ordering is easily understood as well as change in rank over time.</li>
<li> Trends are easily understood over time via the slope. Many suggest using a thin, light gray line to connect the data. A too-heavy line is unnecessary and will make the chart harder to read. If the chart features many lines, judicious use of color can help.</li>
<li> A table (with more statistical detail) might be a good complement to use alongside the slopegraph. As Tufte notes: “The data table and the slopegraph are colleagues in explanation not competitors. One display can serve some but not all functions.”</li>
</ul>
<p>Optionally you can provide important label information through <code>Title</code>, <code>Subtitle</code>, and <code>Caption</code> arguments. You can suppress them all together by setting them <code>= NULL</code> but since I think they are very important the default behavior is to gently remind you, that you have not provided any information. Let's provide a title and sub-title but skip the caption.</p>
<pre><code>newggslopegraph(dataframe = newcancer,
                Times = Year,
                Measurement = Survival,
                Grouping = Type,
                Title = &quot;Estimates of Percent Survival Rates&quot;,
                SubTitle = &quot;Based on: Edward Tufte, Beautiful Evidence, 174, 176.&quot;,
                Caption = NULL
                )
</code></pre>
<p>Gives this plot:<br>
<a rel="nofollow" href="https://i2.wp.com/datascienceplus.com/wp-content/uploads/2018/06/ggslope2-1.png?ssl=1" target="_blank"><img sizes="(max-width: 392px) 100vw, 392px" src="https://i0.wp.com/datascienceplus.com/wp-content/uploads/2018/06/ggslope2-1-392x490.png?resize=392%2C490&ssl=1" alt="" width="392" class="wp-image-14372" data-recalc-dims="1" height="490"></a></p>
<h2>How it all works</h2>
<p>It's all well and good to get the little demo to work, but it might be useful for you to understand how to extend it out to data you're interested in.</p>
<p>You'll need a dataframe with at least three columns. The function will do some basic error checking and complain if you don't hit the essentials.</p>
<ul>
<li> <code>Times</code> is the column in the dataframe that corresponds to the x axis of the plot and is normally a set of moments in time expressed as either characters, factors or ordered factors (in our case <code>newcancer$Year</code>. If it is truly time series data (especially with a lot of dates you're much better off using an R function purpose built for time series). In <code>newcancer</code> it's an ordered factor, mainly because if we fed the information in as character the sort order would be <code>Year 10, Year 15, Year 20, Year 5</code> which is very confusing. A command like <code>newcancer$Year &lt;- factor(newcancer$Year,levels = c(&quot;Year.5&quot;, &quot;Year.10&quot;, &quot;Year.15&quot;, &quot;Year.20&quot;), labels = c(&quot;5 Year&quot;,&quot;10 Year&quot;,&quot;15 Year&quot;,&quot;20 Year&quot;), ordered = TRUE)</code> would be the way to force things they way you want them.</li>
<li> <code>Measurement</code> is the column that has the actual numbers you want to display along the y axis. Frequently that's a percentage but it could just as easily be any number. Watch out for scaling issues here, you'll want to ensure that its not disparate. In our case <code>newcancer$Survival</code> is the percentage of patients surviving at that point in time, so the maximum scale is 0 to 100.</li>
<li> <code>Grouping</code> is what controls how many individual lines are portrayed. Every attempt is made to color them and label them in ways that lead to clarity but eventually you can have too many. In our example case the column is <code>newcancer$Type</code> for the type of cancer or location.</li>
</ul>
<p>As a sidenote, if you're interested in how the function was built and some of the underlying <code>R</code> programming please consider reading <a rel="nofollow" href="https://ibecav.github.io/slopegraph/" target="_blank">this other post</a> about building the function step by step.</p>
<h2>Another quick example</h2>
<p>This is loosely based off a <a rel="nofollow" href="https://ekonometrics.blogspot.com/2018/05/edward-tuftes-slopegraphs-and-political.html" target="_blank">blog post</a> from Murtaza Haider titled Edward Tufte’s Slopegraphs and political fortunes in Ontario. In this case we're going to plot the percent of the vote captured by some Canadian political parties. <i>“The data is loosely based on real data but is not actually accurate”</i></p>
<p><code>moredata$Date</code> is the hypothetical polling date as a factor (in this case <code>character</code> would work equally well). <code>moredata$Party</code> is the various political parties and <code>moredata$Pct</code> is the percentage of the vote they are estimated to have.</p>
<pre><code>moredata &lt;- structure(list(Date = structure(c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L), 
                                            .Label = c(&quot;11-May-18&quot;, &quot;18-May-18&quot;, &quot;25-May-18&quot;), 
                                            class = &quot;factor&quot;), 
                           Party = structure(c(5L, 3L, 2L, 1L, 4L, 5L, 3L, 2L, 1L, 4L, 5L, 3L, 2L, 1L, 4L), 
                                             .Label = c(&quot;Green&quot;, &quot;Liberal&quot;, &quot;NDP&quot;, &quot;Others&quot;, &quot;PC&quot;), 
                                             class = &quot;factor&quot;), 
                           Pct = c(42.3, 28.4, 22.1, 5.4, 1.8, 41.9, 29.3, 22.3, 5, 1.4, 41.9, 26.8, 26.8, 5, 1.4)), 
                      class = &quot;data.frame&quot;, 
                      row.names = c(NA, -15L))
newggslopegraph(moredata,
                Date,
                Pct,
                Party, 
                Title = &quot;Notional data&quot;, 
                SubTitle = NULL, 
                Caption = NULL)</code>
<em>#> #> Converting 'Date' to an ordered factor</em></pre>
<p>Gives this plot:<br>
<a rel="nofollow" href="https://i0.wp.com/datascienceplus.com/wp-content/uploads/2018/06/ggslope3-1.png?ssl=1" target="_blank"><img src="https://i0.wp.com/datascienceplus.com/wp-content/uploads/2018/06/ggslope3-1.png?resize=360%2C360&ssl=1" alt="" width="360" class="wp-image-14373" data-recalc-dims="1" height="360"></a></p>
<p>There are a plethora of formatting options. See <code>?newggslopegraph</code> for all of them. Here's a few.</p>
<pre><code>newggslopegraph(moredata, Date, Pct, Party, 
                Title = &quot;Notional data&quot;, 
                SubTitle = &quot;none&quot;, 
                Caption = &quot;imaginary&quot;,
                LineColor = &quot;gray&quot;, 
                LineThickness = .5,
                YTextSize = 4
                )</code>
<em>Converting 'Date' to an ordered factor</em></pre>
<p>Gives this plot:<br>
<a rel="nofollow" href="https://i1.wp.com/datascienceplus.com/wp-content/uploads/2018/06/ggslope4-1.png?ssl=1" target="_blank"><img src="https://i1.wp.com/datascienceplus.com/wp-content/uploads/2018/06/ggslope4-1.png?resize=360%2C360&ssl=1" alt="" width="360" class="wp-image-14374" data-recalc-dims="1" height="360"></a></p>
<p>The most complex is <code>LineColor</code> where you can do the following if you want to highlight the difference between the Liberal and NDP parties while making the other three less prominent…</p>
<pre><code>newggslopegraph(moredata, Date, Pct, Party, 
                Title = &quot;Notional data&quot;, 
                SubTitle = &quot;none&quot;, 
                Caption = &quot;imaginary&quot;,
                LineColor = c(&quot;Green&quot; = &quot;gray&quot;, &quot;Liberal&quot; = &quot;green&quot;, &quot;NDP&quot; = &quot;red&quot;, &quot;Others&quot; = &quot;gray&quot;, &quot;PC&quot; = &quot;gray&quot;), 
                LineThickness = .5,
                YTextSize = 4
                )</code>
<em>#> #> Converting 'Date' to an ordered factor</em></pre>
<p>Gives this plot:<br>
<a rel="nofollow" href="https://i1.wp.com/datascienceplus.com/wp-content/uploads/2018/06/ggslope5-1.png?ssl=1" target="_blank"><img src="https://i1.wp.com/datascienceplus.com/wp-content/uploads/2018/06/ggslope5-1.png?resize=360%2C360&ssl=1" alt="" width="360" class="wp-image-14375" data-recalc-dims="1" height="360"></a></p>
<h2>One last set of data</h2>
<p>Also from Tufte, this is data about a select group of countries Gross Domestic Product (GDP). I'll use it to show you a tricky way to highlight certain countries without making a named vector with <code>LineColor = c(rep(&quot;gray&quot;,3), &quot;red&quot;, rep(&quot;gray&quot;,3), &quot;red&quot;, rep(&quot;gray&quot;,10))</code> the excess vector entries are silently dropped… The bottom line is that <code>LineColor</code> is simply a character vector that you can fill any way you choose.</p>
<pre><code>newggslopegraph(newgdp, 
                Year, 
                GDP, 
                Country, 
                Title = &quot;Gross GDP&quot;, 
                SubTitle = NULL, 
                Caption = NULL,
                LineThickness = .5,
                YTextSize = 4,
                LineColor = c(rep(&quot;gray&quot;,3), &quot;red&quot;, rep(&quot;gray&quot;,3), &quot;red&quot;, rep(&quot;gray&quot;,10))
                )
</code></pre>
<p>Gives this plot:<br>
<a rel="nofollow" href="https://i2.wp.com/datascienceplus.com/wp-content/uploads/2018/06/ggslope6-1.png?ssl=1" target="_blank"><img sizes="(max-width: 245px) 100vw, 245px" src="https://i0.wp.com/datascienceplus.com/wp-content/uploads/2018/06/ggslope6-1-245x490.png?resize=245%2C490&ssl=1" alt="" width="245" class="wp-image-14376" data-recalc-dims="1" height="490"></a></p>
<p>Finally, let me take a moment about crowding and labeling. I've made every effort to try and deconflict the labels on the left and right axis (in this example the <code>Country</code>) and that should work automatically as you resize your plot dimensions. ** pro tip – if you use <code>RStudio</code> you can press the <code>zoom</code> icon and then use the rescaling of the window to see best choices **. </p>
<p>But the numbers (<code>GDP</code>) are a different matter and there's no easy way to ensure separation in a case like this data. There's a decent total spread from 57.4 to 20.7 and some really close measurements like France, Belgium, and Germany on the right side. My suggestion is in a case like this one you create a new column in your dataframe with two significant places. So specifically it would be <code>newgdp$rGDP &lt;- signif(newgdp$GDP, 2)</code>. In my testing, at least, I've found this helps without creating inaccuracy and not causing you to try and “stretch” vertically to disambiguate the numbers. This time I'll also use <code>LineColor</code> to highlight how Canada, Finland and Belgium fare from 1970 to 1979.</p>
<pre><code>newgdp$rGDP &lt;- signif(newgdp$GDP, 2)
newggslopegraph(newgdp, 
                Year, 
                rGDP, 
                Country, 
                Title = &quot;Gross GDP&quot;, 
                SubTitle = NULL, 
                Caption = NULL,
                LineThickness = .5,
                YTextSize = 4,
                LineColor = c(rep(&quot;gray&quot;,6), rep(&quot;red&quot;,2), &quot;red&quot;, rep(&quot;gray&quot;,10))
                )
</code></pre>
<p>Gives this plot:<br>
<a rel="nofollow" href="https://i2.wp.com/datascienceplus.com/wp-content/uploads/2018/06/ggslope7-1.png?ssl=1" target="_blank"><img sizes="(max-width: 420px) 100vw, 420px" src="https://i2.wp.com/datascienceplus.com/wp-content/uploads/2018/06/ggslope7-1-420x490.png?resize=420%2C490&ssl=1" alt="" width="420" class="wp-image-14377" data-recalc-dims="1" height="490"></a></p>
<h2>One last example and the latest feature</h2>
<p>Returning to the cancer dataset we initially used I recently added a new feature that is only available from the github version of the library. It's called <code>WideLabels</code> and is a simple logical set to <code>FALSE</code> by default. If you change it to <code>TRUE</code> as I have in the next example it will expand the x axis and essentially give you more room for the side labels. This can be very useful in cases like the cancer data where you have a few long complex labels. Here's a made up example where I want to draw the reader's attention to certain cancers which appear to have a more precipitous decline in survival over time.</p>
<pre><code>newggslopegraph(dataframe = newcancer,
                Times = Year,
                Measurement = Survival,
                Grouping = Type,
                Title = &quot;Estimates of Percent Survival Rates&quot;,
                SubTitle = &quot;Based on: Edward Tufte, Beautiful Evidence, 174, 176.&quot;,
                Caption = NULL,
                YTextSize = 2.5,
                LineThickness = .5,
                LineColor = c(&quot;red&quot;, rep(&quot;gray&quot;,4), &quot;red&quot;, rep(&quot;gray&quot;,3)),
                WiderLabels = TRUE
                )</code>
<em>#> #> You gave me 9 colors I'm recycling colors because you have 24 Types</em>
</pre>
<p>Gives this plot:<br>
<a rel="nofollow" href="https://i0.wp.com/datascienceplus.com/wp-content/uploads/2018/06/ggslope9-1.png?ssl=1" target="_blank"><img sizes="(max-width: 327px) 100vw, 327px" src="https://i0.wp.com/datascienceplus.com/wp-content/uploads/2018/06/ggslope9-1-327x490.png?resize=327%2C490&ssl=1" alt="" width="327" class="wp-image-14378" data-recalc-dims="1" height="490"></a></p>
<p>If you like <code>newggslopegraph</code>, please consider filing a GitHub issue by leaving feedback at my <a rel="nofollow" href="https://github.com/ibecav/CGPfunctions/issues" target="_blank">GitHub</a>, or by posting a comment here.</p>
<ul></ul>
<p><strong>
<p>Related Post</p>
<p></p></strong>
<ol>
<li><a rel="nofollow" href="https://datascienceplus.com/how-to-use-paletter-to-automagically-build-palettes-from-pictures/" title="Permanent Link toHow to use paletteR to automagically build palettes from pictures" target="_blank">How to use paletteR to automagically build palettes from pictures</a></li>
<li><a rel="nofollow" href="https://datascienceplus.com/visualize-market-basket-analysis-in-r/" title="Permanent Link toVisualize Market Basket analysis in R" target="_blank">Visualize Market Basket analysis in R</a></li>
<li><a rel="nofollow" href="https://datascienceplus.com/lattice-like-forest-plot-using-ggplot2-in-r/" title="Permanent Link toLattice-Like Forest Plot using ggplot2 in R" target="_blank">Lattice-Like Forest Plot using ggplot2 in R</a></li>
<li><a rel="nofollow" href="https://datascienceplus.com/how-does-visualization-in-plotly-differ-from-seaborn/" title="Permanent Link toHow does visualization in Plotly differ from Seaborn" target="_blank">How does visualization in Plotly differ from Seaborn</a></li>
<li><a rel="nofollow" href="https://datascienceplus.com/twitter-analysis-with-python/" title="Permanent Link toTwitter Analysis with Python" target="_blank">Twitter Analysis with Python</a></li>
</ol>
	<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://datascienceplus.com/creating-slopegraphs-with-r/"> R Programming – DataScience+</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/raabmENvPy8" height="1"></a></div>