├── README.md
└── tbl_bigmac.rmd
/README.md:
--------------------------------------------------------------------------------
1 | # RStudio Table Contest 2020 Submission
2 |
3 | ## [The Big Mac Index Table](https://rpubs.com/acalatroni/682678)
4 |
5 | Our goal for the [2020 RStudio Table Contest](https://blog.rstudio.com/2020/09/15/announcing-the-2020-rstudio-table-contest/) was to learn and practice with the [gt package](https://gt.rstudio.com/). To do so we decided to focus on the following aspects:
6 | - Include interactive figures within the table. For this, we chose the [echarts4r package](https://echarts4r.john-coene.com/) to create interactive graphics with Echarts Javascripts, albeit other packages would have also worked (ie. Plotly, highcharter, etc.)
7 | - Include images, either through a [GitHub](https://github.com/HatScripts/circle-flags) repo (flags) or Wikimedia commons scraping (maps).
8 | - Include as many HTML tricks as necessary to improve the overall readability of the table (for example HTML color of headers, icons, spanners, hyperlinks, currency symbols, scale up the image size (maps) on hover, etc.)
9 | - Include footnotes, in particular a footnote color legend for the color column, an HTML details tab to display in an inconspicuous way the R session information, and font awesome icons for github and twitter hyperlinks).
10 | - Include CSS with the [new feature](https://github.com/rstudio/gt/releases/tag/v0.2.2) `opt_css` to improve the tables aesthetics, especially in light of the interactive graphics tweaking.
11 |
12 | In short the Big Mac Index is published by [The Economist]( https://www.economist.com/) as an informal way of measuring the purchasing power parity (PPP) between two currencies and provides a test of the extent to which market exchange rates result in goods costing the same in different countries. It seeks to make exchange-rate theory a bit more digestible. The magazine's latest version (July 2020) of the [The Big Mac index interactive currency comparison tool](https://www.economist.com/news/2020/07/15/the-big-mac-index). Furthermore, you can also download the data or read the methodology behind the Big Mac index [here]( https://github.com/TheEconomist/big-mac-data)
13 |
--------------------------------------------------------------------------------
/tbl_bigmac.rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "
2020 RStudio Table Contest Submission by A. Calatroni, S. Lussier & R. Krouse Repo "
3 | output:
4 | html_document:
5 | self_containded: TRUE
6 | code_download: yes
7 | code_folding: none # none hide show
8 | toc: false
9 | ---
10 |
11 | ```{r setup, include=FALSE}
12 | knitr::opts_chunk$set(warning = FALSE, message = FALSE, comment = NA, include = FALSE)
13 | knitr::opts_chunk$set(cache = FALSE)
14 | ```
15 |
16 | ```{r}
17 | library(tidyverse)
18 | library(rio)
19 | library(lubridate)
20 | # devtools::install_github("rstudio/gt")
21 | library(gt)
22 | library(countrycode)
23 | library(echarts4r)
24 | library(htmltools)
25 | library(rvest)
26 | library(httr)
27 | ```
28 |
29 | ```{r}
30 | bm_1 <- import("https://raw.githubusercontent.com/TheEconomist/big-mac-data/master/output-data/big-mac-full-index.csv") %>%
31 | select(-starts_with(c("GBP","JPY","CNY"))) %>%
32 | mutate(iso_a2 = countrycode(iso_a3 , origin = 'iso3c', destination = 'iso2c', warn = FALSE),
33 | iso_a2 = str_to_lower(iso_a2),
34 | iso_a2 = ifelse(is.na(iso_a2), "european_union", iso_a2),
35 | iso_fl = str_glue("https://raw.githubusercontent.com/HatScripts/circle-flags/master/flags/{iso_a2}.svg")) %>%
36 | group_by(iso_a3, iso_a2, name, currency_code, iso_fl) %>%
37 | nest_by()
38 |
39 | x_currencies <- import("https://raw.githubusercontent.com/rstudio/gt/master/data-raw/x_currencies.csv") %>%
40 | rename(currency_code = curr_code ) %>%
41 | mutate(curr_name = word(curr_name,-1) %>% str_to_title())
42 |
43 | bm_1 <- left_join(bm_1,
44 | x_currencies,
45 | by = "currency_code")
46 | ```
47 |
48 | ```{r}
49 | # G20 Group of countries
50 | # 2020: Argentina, Australia, Brazil, Canada, China, France, Germany, Italy, India, Indonesia,Japan, Republic of Korea,
51 | # Mexico, Russia, Saudi Arabia, South Africa, Turkey, United Kingdom, United States European Union
52 | # + Switzerland
53 |
54 | bm_g20 <- bm_1 %>%
55 | filter(iso_a3 %in% c("ARG","AUS","BRA","CAN","CHN","EUZ","IND","IDN","JPN","KOR","MEX","RUS","SAU","ZAF","TUR","USA",
56 | "CHE")) %>%
57 | mutate( name_map = name,
58 | name_map = case_when(name_map == "Euro area" ~ "Europe-EU",
59 | name_map == "Russia" ~ "Russian Federation",
60 | name_map == "China" ~ "People's_Republic_of_China",
61 | TRUE ~ as.character(name_map)
62 | )) %>%
63 | mutate(last = list( data %>% slice(n())) ) %>%
64 | mutate( map = list(
65 | glue::glue("https://commons.wikimedia.org/wiki/File:{str_replace_all(name_map,' ', '_')}_(orthographic_projection).svg") %>%
66 | read_html() %>%
67 | html_nodes("img") %>%
68 | html_attr("src") %>%
69 | as.data.frame() %>%
70 | transform(`.` = as.character(`.`)) %>%
71 | filter(grepl("orthographic", ., perl=TRUE)) %>%
72 | slice(1) %>%
73 | pull()
74 | )
75 | ) %>%
76 | unnest(last) %>%
77 | ungroup() %>%
78 | arrange(desc(USD_raw))
79 | ```
80 |
81 | ```{r}
82 | chart <- function(data = data, variable = variable, name = name,
83 | start = start, end = end,
84 | width = width, height = height){
85 |
86 | d <- data %>%
87 | select(date, var = variable) %>%
88 | mutate(date = as.Date(date)) %>%
89 | drop_na(var)
90 |
91 | m <- mean(d %>% pull(var))
92 |
93 | e <- d %>%
94 | e_charts(x = date,
95 | width = width,
96 | height = height
97 | ) %>%
98 | e_bar(var,
99 | name = name,
100 | barWidth = "75%") %>%
101 | e_legend(show = FALSE) %>%
102 | e_y_axis(show = FALSE,
103 | max = 1.0,
104 | min = -1.0) %>%
105 | e_x_axis(show = FALSE,
106 | min = start,
107 | max = end) %>%
108 | e_axis_pointer(label = list(show = FALSE)) %>%
109 | e_visual_map(
110 | type = "piecewise",
111 | pieces = list(list(gt = 0,
112 | color = "#0571B0"),
113 | list(lte = 0,
114 | color = "#CA0020")
115 | ),
116 | show = FALSE,
117 | )
118 |
119 | if ( abs(m)>0 && nrow(d)>0 ) {
120 | e <- e %>%
121 | e_mark_line(data = list(yAxis = 0),
122 | title = '',
123 | silent = TRUE,
124 | symbol = 'none',
125 | animation = FALSE,
126 | label = list(show = TRUE,
127 | postion = 'end',
128 | distance = 0),
129 | lineStyle = list(color = '#bfbfbf',
130 | type = 'solid')
131 | ) %>%
132 | e_mark_area(data = list(
133 | list(xAxis = '2011-06-01', yAxis = -1.0),
134 | list(xAxis = '2020-08-01', yAxis = 1.0)),
135 | itemStyle = list(color = '#f2f2f2')) %>%
136 | e_tooltip( trigger = "axis",
137 | axisPointer = list(type = 'shadow'),
138 | confine = TRUE,
139 | formatter = e_tooltip_pointer_formatter("percent", digits = 1),
140 | textStyle = list(fontSize = 10),
141 | padding = 2)
142 | }
143 | e
144 | }
145 | ```
146 |
147 | ```{r}
148 | bm_g20 <- bm_g20 %>%
149 | rowwise() %>%
150 | mutate(eraw = list(chart(data,
151 | variable = "USD_raw", name = "Raw",
152 | start = '2000-03-01',
153 | end = '2020-08-01',
154 | width = 150, height = 50)),
155 | eadj = list(chart(data,
156 | variable = "USD_adjusted", name = "Adj",
157 | start = '2011-06-01',
158 | end = '2020-08-01',
159 | width = 75, height = 50))
160 | ) %>%
161 | mutate(eraw_html = list( eraw %>%
162 | as.tags() %>%
163 | as.character() %>%
164 | htmltools::HTML() ),
165 | eadj_html = list( eadj %>%
166 | as.tags() %>%
167 | as.character() %>%
168 | htmltools::HTML() )
169 | )
170 | ```
171 |
172 |
173 | ```{r}
174 | detach("package:rvest", unload = TRUE)
175 | detach("package:httr", unload = TRUE)
176 | ```
177 |
178 | ```{r}
179 | chart(data = bm_g20 %>% filter(iso_a3 == "ARG") %>% select(data) %>% unnest(),
180 | variable = "USD_raw", name = "Raw",
181 | start = '2000-01-01',
182 | end = '2021-01-01',
183 | width = 150, height = 50)
184 | ```
185 |
186 | ```{r include = TRUE, echo = FALSE}
187 | tab_0 <- bm_g20 %>%
188 | select(iso_fl, map, name, iso_a3,
189 | currency_code, curr_name, symbol,
190 | date, local_price, dollar_price,
191 | USD_raw, USD_adjusted, eraw_html, eadj_html) %>%
192 | gt() %>%
193 | # add country hyperlink
194 | text_transform(
195 | locations = cells_body(
196 | columns = vars(name)
197 | ),
198 | fn = function(x) {
199 | glue::glue("{x} ")
200 | }
201 | ) %>%
202 | # add flags
203 | text_transform(
204 | locations = cells_body(
205 | columns = vars(iso_fl)
206 | ),
207 | fn = function(x) {web_image(url = x, height = 30)}
208 | ) %>%
209 | # add maps
210 | text_transform(
211 | locations = cells_body(
212 | columns = vars(map)
213 | ),
214 | fn = function(x) {web_image(url = x, height = 50)}
215 | ) %>%
216 | # merge currency name & code
217 | cols_merge(columns = vars(curr_name, currency_code),
218 | pattern = html("{1} ({2} )") )
219 |
220 | # merge currencies to local price
221 | for (i in seq(nrow(bm_g20))) {
222 | tab_0 <- tab_0 %>%
223 | fmt_currency(columns = vars(local_price),
224 | rows = i,
225 | currency = bm_g20[[i, "currency_code"]])
226 | }
227 |
228 | tab_1 <- tab_0 %>%
229 | # remove unused variables
230 | cols_hide(columns = vars(iso_a3, symbol, date)) %>%
231 | # rename variables
232 | cols_label( iso_fl = ' ',
233 | map = ' ',
234 | name = 'Country',
235 | curr_name = html('Currency (Abbr) '),
236 | date = html('Date (yy-mm) '),
237 | eraw_html = html("2000 → 2011 → 2020 Raw"),
238 | eadj_html = html("2011 → 2020 Adjusted")
239 | ) %>%
240 | # align data
241 | cols_align(align = "center",
242 | columns = vars(map, local_price, dollar_price, USD_raw, USD_adjusted)) %>%
243 | cols_align(align = "left",
244 | columns = vars(name, curr_name)) %>%
245 | # align columns labels
246 | tab_style(
247 | style = list(
248 | cell_text(align = "left")
249 | ),
250 | locations = cells_column_labels(
251 | columns = vars(name, curr_name)
252 | )
253 | ) %>%
254 | # make map square cell
255 | cols_width(
256 | vars(map) ~ px(60)
257 | ) %>%
258 | # format missing
259 | fmt_missing( columns = vars(USD_adjusted),
260 | missing_text = html("—")
261 | ) %>%
262 | # format percent
263 | fmt_percent(columns = vars(USD_raw, USD_adjusted),
264 | decimals = 1) %>%
265 | # round dollar price
266 | fmt_number(columns = vars(dollar_price),
267 | decimals = 2) %>%
268 | # add dollar sign
269 | fmt_currency(columns = vars(dollar_price),
270 | currency = "USD") %>%
271 | # spanner
272 | tab_spanner(
273 | label = html("🏷️ Latest Price"),
274 | columns = vars(local_price, dollar_price)
275 | ) %>%
276 | # spanner
277 | tab_spanner(
278 | label = html("💵 USD under /over "),
279 | columns = vars(USD_raw, USD_adjusted)
280 | ) %>%
281 | # Spanner
282 | tab_spanner(
283 | label = html("⏱️ Historical Data"),
284 | columns = vars(eraw_html, eadj_html)
285 | ) %>%
286 | # labels
287 | cols_label(local_price = "Local",
288 | dollar_price = "Dollar" ) %>%
289 | cols_label(USD_raw = "Raw",
290 | USD_adjusted = "Adjusted" ) %>%
291 | # Add color USD Raw & Udjusted
292 | data_color(
293 | columns = vars(USD_raw, USD_adjusted),
294 | colors = scales::col_bin(
295 | bins = c(-Inf, 0, Inf),
296 | palette = c("#CA0020","#0571B0")
297 | ),
298 | apply_to = "text"
299 | ) %>%
300 | # Add color to dollar price RColorBrewer::brewer.pal(11,"RdYlBu")[1:10]
301 | data_color(
302 | columns = vars(dollar_price),
303 | colors = scales::col_bin(
304 | palette = c("#A50026","#D73027","#F46D43","#FDAE61","#FEE090",
305 | "#FFFFBF",
306 | "#E0F3F8","#ABD9E9","#74ADD1", "#4575B4"),
307 | domain = c(0,1,2,3,4,5,6,7,8,9,10),
308 | bins = 10),
309 | alpha = 0.5
310 | )%>%
311 | # make cells bold
312 | tab_style(
313 | style = list(
314 | cell_text(weight = "bold")
315 | ),
316 | locations = cells_body(
317 | columns = vars(USD_raw, USD_adjusted)
318 | )
319 | ) %>%
320 | # make US the baseline
321 | tab_style(
322 | style = cell_fill(color = "#FFFFBF", alpha = 0.5),
323 | locations = cells_body(
324 | rows = name == "United States"
325 | )
326 | ) %>%
327 | # add a title
328 | tab_header(
329 | title = md("**Burgernomics:** The Big Mac 🍔 Index for [G20](https://en.wikipedia.org/wiki/G20) compared to the US Dollar"),
330 | subtitle = md("Measuring the purchasing power parity (PPP) between two currencies")
331 | ) %>%
332 | # add source
333 | tab_source_note(
334 | html('
335 | Source:
336 |
337 | The Economist: The Big Mac Index introduced in 1986 as a semi-humorous illustration of PPP and has been published since then.
338 |
339 | The Economist Big Mac index
340 |
341 | Data and methodology
342 | ')
343 |
344 | ) %>%
345 | tab_source_note( md( { details::details(devtools::session_info(),
346 | summary = 'R Session Information'
347 | )
348 | }
349 | )
350 | ) %>%
351 | # footnotes
352 | tab_footnote(
353 | footnote = "Data as of 2020-07-01",
354 | locations = cells_column_spanners(html("🏷️ Latest Price"))
355 | ) %>%
356 | tab_footnote(
357 | footnote =
358 | "The index is based on the theory of PPP, the notion that in the long run exchange rates should move towards the rate
359 | that would equalise the prices of an identical basket of goods and services (in this case, a burger) in any two countries.",
360 | locations = cells_title("subtitle")
361 | ) %>%
362 | tab_footnote(
363 | footnote = "Raw Index: % cost difference than in the US",
364 | locations = cells_column_labels(vars(USD_raw,eraw_html))
365 | ) %>%
366 | tab_footnote(
367 | footnote = "GDP Adjusted Index: % cost difference than in the US based on differences in GDP between the two countries",
368 | locations = cells_column_labels(vars(USD_adjusted,eadj_html))
369 | ) %>%
370 | tab_footnote(
371 | footnote = "Base Currency",
372 | locations = list( cells_title("title"),
373 | cells_body( columns = vars(local_price, dollar_price),
374 | rows = name == "United States")
375 | )
376 | ) %>%
377 | tab_footnote(
378 | footnote = md('ABBR: Three-character [ISO 4217 currency code](https://www.iso.org/iso-4217-currency-codes.html)'),
379 | locations = cells_column_labels(vars(curr_name))
380 | ) %>%
381 | tab_footnote(
382 | footnote = html('Price of a Big Mac in the local currency'),
383 | locations = cells_column_labels(vars(local_price))
384 | ) %>%
385 | tab_footnote(
386 | footnote = html('Price of a Big Mac in dollars
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 | $0-1
399 | 1-2
400 | 2-3
401 | 3-4
402 | 4-5
403 | 5-6
404 | 6-7
405 | 7-8
406 | 8-9
407 | 9-10
408 | '),
409 | locations = cells_column_labels(vars(dollar_price))
410 | ) %>%
411 | # transparent trick: do not print 0%
412 | tab_style(
413 | style = cell_text(color = 'transparent'),
414 | locations = cells_body(
415 | columns = vars(USD_raw, USD_adjusted),
416 | rows = name == "United States")
417 | ) %>%
418 | # add options left align
419 | opt_align_table_header( align = "left") %>%
420 | # upper
421 | opt_all_caps(locations = "column_labels") %>%
422 | # theme compact
423 | tab_options(table.font.size = px(14),
424 | data_row.padding = px(1),
425 | footnotes.padding = px(1),
426 | source_notes.padding = px(1),
427 | row_group.padding = px(1)) %>%
428 | # add CSS
429 | opt_css(css = ".html-widget {margin-bottom: 0px;}") %>%
430 | opt_css(css = ".gt_row:nth-child( 9){overflow-y: hidden;}") %>%
431 | opt_css(css = ".gt_row:nth-child(10){overflow-y: hidden;}") %>%
432 | opt_css(css = ".gt_row:nth-child( 2):hover{transform: scale(2);}") %>%
433 | # change font
434 | opt_table_font(
435 | font = list(google_font(name = "Source Sans Pro"))
436 | )
437 |
438 | tab_1
439 | ```
440 |
--------------------------------------------------------------------------------