-
Notifications
You must be signed in to change notification settings - Fork 25
/
index.html
326 lines (277 loc) · 17.5 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<title>rCharts</title>
<link rel="stylesheet" href="libraries/frameworks/minimal/stylesheets/styles.css">
<link rel="stylesheet" href="libraries/highlighters/highlight.js/css/solarized_dark.css">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<script src="libraries/widgets/polycharts/js/polychart2.standalone.js"></script>
</head>
<body>
<div class="wrapper">
<header>
<h1>rCharts</h1>
<p>Shiny Applications</p>
<p class="view">
<a href="http://github.com/ramnathv/rChartsShiny">
View the Project on GitHub <small>ramnathv/rChartsShiny</small>
</a>
</p>
<ul>
<li><a href="https://github.com/ramnathv/rChartsShiny/zipball/gh-pages">
Download <strong>ZIP File</strong>
</a></li>
<li><a href="https://github.com/ramnathv/rChartsShiny/tarball/gh-pages">
Download <strong>TAR Ball</strong>
</a></li>
<li><a href="http://github.com/ramnathv/rChartsShiny">
Fork On <strong>GitHub</strong></a>
</li>
</ul>
</header> <section>
<h2>Interactive Visualizations with rCharts and Shiny</h2>
<style>
p {
text-align: justify;
}
body {
background-image: url(libraries/frameworks/minimal/images/light_wool.png)
}
</style>
<p>In this blog post, I will take you through the details of creating an interactive visualization using <a href="http://ramnathv.github.io/rCharts">rCharts</a> and <a href="http://rstudio.github.io/shiny">Shiny</a>. I will be attempting to replicate <a href="http://www.oecd.org/gender/data/proportionofemployedwhoareseniormanagersbysex.htm">this visualization</a> of senior manager percentages by gender across countries, put together by OECD using <a href="http://www.tableausoftware.com">Tableau</a>. Here is the <a href="http://glimmer.rstudio.com/ramnathv/rChartOECD/">final shiny app</a> that we will be building.</p>
<h2>Data</h2>
<p>The data was collected by the International Labor Organization. I used a version of the dataset put together by the excellent data visualization blog: <a href="http://thewhyaxis.info/gap-remake/">thewhyaxis</a>. I cleaned up the dataset, partially in excel and then in R to get the following (more details on the clean up excercise in R can be found in the github repo)</p>
<pre><code> country countrycode year id gender value
1 OECD OECD 1995 1 Men 9.4
3 Austria AUT 1995 3 Men 9.5
4 Belgium BEL 1995 4 Men 12.2
5 Canada CAN 1995 5 Men 13.2
7 Czech Republic CZE 1995 7 Men 8.0
8 Denmark DNK 1995 8 Men 9.6
</code></pre>
<p>We now proceed to creating an interactive visualization. If you want to follow along, you would need to install <code>rCharts</code>, an R package that provides a <a href="http://cran.r-project.org/web/packages/lattice/index.html">lattice</a> package style plotting interface to create interactive visualizations using the javascript library <a href="https://github.com/Polychart/polychart2">polychart.js</a>.</p>
<pre><code class="r">require(devtools)
install_github("rCharts", "ramnathv")
</code></pre>
<h2>First Steps</h2>
<p>Our first objective is to recreate the charts here without any menu controls. Once we are able to achieve that, we can add the menu controls easily using Shiny and convert it into an interactive app. This blog post will attemp to show you both how to use rCharts to create such visualizations, as well as how to convert them into an interactive app using Shiny.</p>
<h3>Bar Plot</h3>
<p>We will now recreate the bar plot shown in the Tableau visualization.</p>
<div id='chart1'></div>
<pre><code class="r">require(rCharts)
YEAR = 2011
# Step 1. create subsets of data by gender
men <- subset(dat2m, gender == "Men" & year == YEAR)
women <- subset(dat2m, gender == "Women" & year == YEAR)
# Step 2. initialize bar plot for value by countrycode for women
p1 <- rPlot(x = list(var = "countrycode", sort = "value"), y = "value",
color = 'gender', data = women, type = 'bar')
# Step 3. add a second layer for men, displayed as points
p1$layer(x = "countrycode", y = "value", color = 'gender',
data = men, type = 'point', size = list(const = 3))
# Step 4. format the x and y axis labels
p1$guides(x = list(title = "", ticks = unique(men$countrycode)))
p1$guides(y = list(title = "", max = 18))
# Step 5. set the width and height of the plot and attach it to the dom
p1$addParams(width = 600, height = 300, dom = 'chart1',
title = "Percentage of Employed who are Senior Managers")
# Step 6. print the chart (just type p1 if you are using it in your R console)
p1$print()
</code></pre>
<div id='chart1' class='rChart polycharts'></div>
<script type='text/javascript'>
var chartParams = {
"dom": "chart1",
"width": 600,
"height": 300,
"layers": [
{
"x": {
"var": "countrycode",
"sort": "value"
},
"y": "value",
"data": {
"country": [ "OECD", "Austria", "Belgium", "Czech Republic", "Denmark", "Estonia", "Finland", "France", "Germany", "Greece", "Hungary", "Iceland", "Ireland", "Italy", "Luxembourg", "Netherlands", "Norway", "Poland", "Portugal", "Slovak Republic", "Slovenia", "Spain", "Sweden", "Switzerland", "United Kingdom" ],
"countrycode": [ "OECD", "AUT", "BEL", "CZE", "DNK", "EST", "FIN", "FRA", "DEU", "GRC", "HUN", "ISL", "IRL", "ITA", "LUX", "NLD", "NOR", "POL", "PRT", "SVK", "SVN", "ESP", "SWE", "CHE", "GBR" ],
"year": [ 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011 ],
"id": [ 1, 3, 4, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 21, 23, 25, 26, 27, 28, 29, 30, 31, 32, 34 ],
"gender": [ "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women" ],
"value": [ 4.4, 3, 4.7, 2.8, 1.6, 6.5, 3.4, 6.2, 3.2, 2.4, 5, 7.5, 5.3, 2.4, 2.4, 4.7, 4.3, 5.2, 4.3, 3.7, 6.9, 3.3, 4, 5.7, 7.5 ]
},
"facet": null,
"color": "gender",
"type": "bar"
},
{
"x": "countrycode",
"y": "value",
"data": {
"country": [ "OECD", "Austria", "Belgium", "Czech Republic", "Denmark", "Estonia", "Finland", "France", "Germany", "Greece", "Hungary", "Iceland", "Ireland", "Italy", "Luxembourg", "Netherlands", "Norway", "Poland", "Portugal", "Slovak Republic", "Slovenia", "Spain", "Sweden", "Switzerland", "United Kingdom" ],
"countrycode": [ "OECD", "AUT", "BEL", "CZE", "DNK", "EST", "FIN", "FRA", "DEU", "GRC", "HUN", "ISL", "IRL", "ITA", "LUX", "NLD", "NOR", "POL", "PRT", "SVK", "SVN", "ESP", "SWE", "CHE", "GBR" ],
"year": [ 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011 ],
"id": [ 1, 3, 4, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 21, 23, 25, 26, 27, 28, 29, 30, 31, 32, 34 ],
"gender": [ "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men" ],
"value": [ 7.7, 6.8, 9.2, 6.2, 3.8, 11.6, 6.8, 8.6, 6.4, 5.4, 6.3, 10.4, 9.3, 5, 5.7, 9.6, 8.5, 6.8, 7.8, 6.5, 9.4, 6.3, 6.8, 9.6, 12.5 ]
},
"facet": null,
"color": "gender",
"type": "point",
"size": {
"const": 3
}
}
],
"facet": [],
"guides": {
"x": {
"title": "",
"ticks": [ "OECD", "AUT", "BEL", "CZE", "DNK", "EST", "FIN", "FRA", "DEU", "GRC", "HUN", "ISL", "IRL", "ITA", "LUX", "NLD", "NOR", "POL", "PRT", "SVK", "SVN", "ESP", "SWE", "CHE", "GBR" ]
},
"y": {
"title": "",
"max": 18
}
},
"coord": [],
"title": "Percentage of Employed who are Senior Managers",
"id": "chart1"
}
_.each(chartParams.layers, function(el){
el.data = polyjs.data(el.data)
})
var graph_chart1 = polyjs.chart(chartParams);
</script>
<p>The first step is to create subsets of the data by gender for a specific year. We then proceed to initialize a bar plot for <code>women</code>. The function <code>rPlot</code> uses an interface very similar to the <code>lattice</code> package. The first argument specifies that the x variable is going to be <code>countrycode</code> and we want it sorted by <code>value</code>. The remaining arguments specify different aesthetics of the bar plot.</p>
<p>The next step adds a second layer to this plot using the data for <code>men</code>, specifying that the values be displayed as <code>points</code>. The code in <strong>Step 3</strong> might seem a little strange to some of you, since there is no explicit assignment involved. The reason for this is that <code>rCharts</code> uses <a href="">Reference Classes</a>, which allow object oriented programming in R, leading to more concise code. In essence, <code>layer2</code> is a method of the object <code>p1</code> that adds a layer to the plot object. </p>
<p>The last few steps tweak the axis labels, width and height of the plot, before attaching it to a specific DOM element. At this point, you can run Steps 1 through 5 and type <code>p1</code> in your R console, and if everything goes right, you will be staring at the same plot created here.</p>
<h3>Line Chart</h3>
<p>We can now add a line chart for comparing the values for a specific country across years. We follow the same approach outlined above, except that we only need a single layer in this case.</p>
<div id='chart2'></div>
<pre><code class="r">COUNTRY = "Canada"
country = subset(dat2m, country == COUNTRY)
p2 <- rPlot(value ~ year, color = 'gender', type = 'line', data = country)
p2$addParams(width = 600, height = 300, dom = 'chart2')
p2$guides(y = list(min = 0, title = ""))
p2$print()
</code></pre>
<div id='chart2' class='rChart polycharts'></div>
<script type='text/javascript'>
var chartParams = {
"dom": "chart2",
"width": 600,
"height": 300,
"layers": [
{
"x": "year",
"y": "value",
"data": {
"country": [ "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada" ],
"countrycode": [ "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN" ],
"year": [ 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 ],
"id": [ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 ],
"gender": [ "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Men", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women", "Women" ],
"value": [ 13.2, 12.8, 11.7, 11.2, 11.6, 11.7, 11, 11.1, 10.7, 11, 11.1, 11.2, 10.9, 11.3, 8.4, 8.8, 8.1, 8.2, 7.4, 7.5, 6.9, 6.6, 6.8, 7.2, 7, 7.2, 7.1, 7.1 ]
},
"facet": null,
"color": "gender",
"type": "line"
}
],
"facet": [],
"guides": {
"y": {
"min": 0,
"title": ""
}
},
"coord": [],
"id": "chart2"
}
_.each(chartParams.layers, function(el){
el.data = polyjs.data(el.data)
})
var graph_chart2 = polyjs.chart(chartParams);
</script>
<h3>Shiny App</h3>
<p>Now that we have created the charts for a given <code>COUNTRY</code> and <code>YEAR</code>, we can go ahead and wrap the code in a Shiny app to allow users to interactively choose the inputs. To create a Shiny app, we need two files: <code>ui.R</code> that specifies the user interface and <code>server.R</code> that specifies how to generate outputs.</p>
<h4>User Interface (ui.R)</h4>
<p>Let us design the user interface first. Note that we need four components, two select boxes to allow the user to select the year and country, and two <code>div</code> tags to place the dynamically generated chart output.</p>
<pre><code class="r">require(rCharts)
options(RCHART_LIB = 'polycharts')
shinyUI(pageWithSidebar(
headerPanel("Percentage of Employed who are Senior Managers, by Sex"),
sidebarPanel(
selectInput(inputId = "year",
label = "Select year to compare countries",
choices = sort(unique(dat2m$year)),
selected = 2011),
selectInput(inputId = "country",
label = "Select country to compare years",
choices = sort(unique(dat2m$country)),
selected = "Canada")
),
mainPanel(
showOutput("chart1", "polycharts"),
showOutput("chart2", "polycharts")
)
))
</code></pre>
<p>Although the above code is self explanatory, I want to draw your attention to a couple of things. First, we choose a layout where the controls are placed in a sidebar and the charts in the main panel. Second, we generate the choices for the two selection boxes using the unique values for <code>year</code> and <code>country</code> in the dataset. Third, <code>showOutput</code> is a function in <code>rCharts</code> that creates placeholders for the generated charts, with a given id.</p>
<h4>Chart Output (server.R)</h4>
<p>Now that we nailed the UI, we need to tweak the plotting code to interface with the UI. To achieve this, we need to do three things. First, we need to replace COUNTRY and YEAR by <code>input$country</code> and <code>input$year</code> so that their values are dynamically obtained from user input. Second, we need to wrap the plotting calls inside <code>renderChart</code>, which is a function in <code>rCharts</code> that adds allows the plots to react to user inputs. Third, we need to assign the output of these calls to their respective elements in the UI (chart1 and chart2).</p>
<pre><code class="r">require(rCharts)
options(RCHART_WIDTH = 800)
shinyServer(function(input, output) {
output$chart1 <- renderChart({
YEAR = input$year
men <- subset(dat2m, gender == "Men" & year == YEAR)
women <- subset(dat2m, gender == "Women" & year == YEAR)
p1 <- rPlot(x = list(var = "countrycode", sort = "value"), y = "value",
color = 'gender', data = women, type = 'bar')
p1$layer(x = "countrycode", y = "value", color = 'gender',
data = men, type = 'point', size = list(const = 3))
p1$addParams(height = 300, dom = 'chart1',
title = "Percentage of Employed who are Senior Managers")
p1$guides(x = list(title = "", ticks = unique(men$countrycode)))
p1$guides(y = list(title = "", max = 18))
return(p1)
})
output$chart2 <- renderChart({
COUNTRY = input$country
country = subset(dat2m, country == COUNTRY)
p2 <- rPlot(value ~ year, color = 'gender', type = 'line', data = country)
p2$guides(y = list(min = 0, title = ""))
p2$guides(y = list(title = ""))
p2$addParams(height = 300, dom = 'chart2')
return(p2)
})
})
</code></pre>
<p>Finally, we place the code required to read and process the data in <code>global.R</code> so that the data is accessible to both <code>ui.R</code> and <code>server.R</code>. You can see the resulting <a href="http://glimmer.rstudio.com/ramnathv/rChartOECD">Shiny app here</a> and the <a href="https://github.com/ramnathv/rChartsShiny/tree/gh-pages/rChartOECD">source code</a> </p>
<h3>Notes</h3>
<p>This blog post is a github repo and is reproducible using the <a href="http://slidify.org">slidify</a> package. You can download/clone this repo and run <code>slidify("index.Rmd")</code> to reproduce the entire post along with the embedded charts. If you have any questions or comments, please use the <a href="https://github.com/ramnathv/rChartsShiny/issues/new">issues page</a>, tagging it appropriately.</p>
<h3>License</h3>
<p><code>rCharts</code> is licensed under the MIT License. However, the Polycharts JavaScript library used to create these charts is not free for commercial use. You can read more about its license at <a href="http://polychart.com/js/license">http://polychart.com/js/license</a>.</p>
</section>
<footer>
<p>This project is maintained by <a href="http://github.com/ramnathv">
Ramnath Vaidyanathan
</a></p>
<p><small>Hosted on GitHub Pages — Theme by
<a href="https://github.com/orderedlist">orderedlist</a></small>
</p>
</footer> </div>
<script src="libraries/frameworks/minimal/javascripts/scale.fix.js"></script>
</body>
<!-- Load Javascripts for Widgets -->
<!-- LOAD HIGHLIGHTER JS FILES -->
<script src="libraries/highlighters/highlight.js/highlight.pack.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
<!-- DONE LOADING HIGHLIGHTER JS FILES -->
</html>