-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCOVIDEDA.Rmd
executable file
·178 lines (136 loc) · 7.12 KB
/
COVIDEDA.Rmd
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
---
title: "Coronavirus Exploratory Data Analysis"
author: "Luis Chaves"
date: 'Last updated: `r file.info("Plots")$mtime`'
runtime: shiny
output:
html_document:
toc: true
code_folding: hide
theme: united
resource_files:
- Plots/
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = T,warnings = FALSE, message = FALSE)
```
### Load necessary libraries
We simply need 3 libraries as most of our scripts ran offline.
```{r}
library(shiny) ## for UI
library(plotly) ## for renderPlotly function
library(leaflet) ## for renderLeaflet function
```
# Introduction
## Greetings
You may come from my Medium series on creating an interactive report or you may note. Either way I hope you can learn from this notebook!
## Load data
First we need to load our plots that we created with the various scripts (Treemaps, line plots and a map). We could alternatively compute the plots at runtime but that will likely result in a slower load time, annoying the reader of our Shiny document. Because we saved all of our plots (including the Leaflet maps) as RDS objects we can load them all using a single loop instead of having to list them all.
```{r LoadPlots}
## Iterate through all the files under the Plots directory
for (file in list.files("Plots/")){
# assign each file to a variable with the same name as the file
# but without the file extension. Equivalent to:
# filename = load(filename.filextension)
assign(x = strsplit(file, '\\.')[[1]][1],
value = readRDS(paste0("Plots/",file)))
}
```
# Main Plots
Now that we have loaded the plots, we simply need to design the Shiny UI, which is composed of an input element and of rendering functions that react to the changes in the input.
## Treemap Charts
An input block looks like this:
```{r class.source="fold-show"}
treemap_input = selectInput(inputId = "treemap_choice",
label = "Event/Metric",
choices = c("Deaths(D)", "Confirmed(C)", "Fataily-Case Ratio"),
selected = "Deaths(D)")
```
The first argument is the input handle which __Shiny__ is going to use to refer to this input. Next is the label of this input handle (`label`) which will appear right above the handle, then the possible choices (`choices`) and finally the default choice (`selected`). Other input handling function exist, such as: `fileInput()`, `dateInput()`, `sliderInput()`, `checkboxInput()` and others.
Once, we got the input handling function ready, we just need a `render*()` function that handles the input, such as `renderPlotly()`, `renderImage()`, `renderText()` or others. Here we will use `renderPlotly()`
```{r}
treemap_input ## <-- this calls the input handlers and displays them
```
```{r class.source="fold-show"}
renderPlotly(
if (input$treemap_choice == "Deaths(D)"){
treemap_deaths
} else if (input$treemap_choice == "Confirmed(C)") {
treemap_cases
} else if (input$treemap_choice == "Fataily-Case Ratio") {
treemap_deaths_by_cases
}
)
```
__Now, it's just play and repeat!__
## Line plots
### Cumulative and Daily number of events over time
We can also open a new _Input_ handling function when a parent _Input_ function returns a certain value. The line plots offer a great example to do this: we can have a handle for Daily/Cumulative, another for Country/Continent, another one for Deaths/Cases and a final one to enable log10 scale. First we are going to define our input handlers:
```{r class.source="fold-show"}
line_geo = selectInput(inputId = "line_choice_geography",
label = "Geography",
choices = c("Country", "Continent"),
selected = "Continent")
line_mode = selectInput(inputId = "line_choice_mode",
label = "Mode",
choices = c("Daily", "Cumulative"),
selected = "Cumulative")
line_event = selectInput(inputId = "line_choice_event",
label = "Event",
choices = c("Death", "Cases"),
selected = "Cases")
line_log10 = checkboxInput('line_log10', 'log10 scale', value = FALSE)
```
Once, we got the input handling function ready, we just need a `render*()` function that handles the input, such as `renderPlotly()`, `renderImage()`, `renderText()` or others. Here we are going to take advantage of the fact that our plot names are standardised to make the logic more concise(see below).
| **Continent plots** | **Country plots** |
|-------------------------------------------|-----------------------------------|
| `plotly_cases_time_continent` | `plotly_cases_time_country` |
| `plotly_cases_time_continent_daily` | `plotly_cases_time_country_daily` |
| `plotly_deaths_time_continent` | `plotly_deaths_time_country` |
| `plotly_deaths_time_continent_daily` | `plotly_deaths_time_country_daily`|
| `plotly_cases_time_continent_log10` | *Not created* |
| `plotly_cases_time_continent_log10_daily` | *Not created* |
| `plotly_deaths_time_continent_log10` | *Not created* |
| `plotly_deaths_time_continent_log10_daily`| *Not created* |
Depending on the inputs, we are going to build a string corresponding to one of the plot names using the `ifelse()` function. The logic for the geography choice is even more special because if __"Continent"__ is chosen we will create a checkbox to enable log10 scale. To do this we use what;s called a conditional panel as seen in the next code chunk, additionally we are going to wrap all of our input handlers in side an `inputPanel()` which will make them look very good and tidy.
```{r}
inputPanel(
line_event,
line_mode,
line_geo,
conditionalPanel('input.line_choice_geography == "Continent"', line_log10)
)
```
```{r}
renderPlotly({
event = ifelse(input$line_choice_event == 'Cases', 'cases', 'deaths')
mode = ifelse(input$line_choice_mode == 'Daily', '_daily', '')
if(input$line_choice_geography == 'Country') {
geography = 'country'
log10 = ''
} else {
geography = 'continent'
log10 = ifelse(input$line_log10, '_log10', '')
}
# build string
chosen_plot = paste0('plotly_', event, '_time_',geography,log10, mode)
# parse and evaluate content of the string
eval(parse(text = chosen_plot))
}
)
```
You may sometimes find negative daily count of cases or deaths for a certain country. This turns out to be a not-so-rare artefact where a country may have overestimated their number of cases/deaths on a given date and rectifies at a later date what its actual numbers are.
## COVID19 over space - Maps
We done some pretty neat job with the previous Shiny UI. The last one is simple, we'll make use of the `renderLeaflet()` function this time.
This map reflect the number of cases/deaths in each country by `r Sys.Date()`.
```{r}
selectInput('map',
label = 'Event',
choices = c('Deaths', 'Cases'),
selected = 'Cases')
renderLeaflet({
if(input$map == 'Deaths'){mapdeaths} else {mapcases}
})
```
# Appendix - Extra plots
One day I may decide to fill this.