├── README.Rmd
├── README.md
├── global.R
├── life_exp.csv
├── server.R
├── ui.R
└── www
├── busy.js
├── google-analytics.js
├── loader.gif
├── md5.js
├── passwdInputBinding.js
├── rocky.wav
├── sound.js
└── style.css
/README.Rmd:
--------------------------------------------------------------------------------
1 | ## Shiny tips and trics application
2 |
3 | ### Data
4 |
5 | The dataset contains the life expectanncy of males and females in different countries in the world. It is based on babies that are born in 2015. I downloaded the dataset from
6 | [wikipedia](https://en.wikipedia.org/wiki/List_of_countries_by_life_expectancy)
7 |
8 |
9 | ```{r}
10 | 'data.frame': 171 obs. of 7 variables:
11 | $ country : chr "Afghanistan" "Albania" "Algeria" "Angola" ...
12 | $ region : chr "Asia" "Europe" "Africa" "Africa" ...
13 | $ population: int 32526562 2896679 39666519 25021974 91818 43416755 3017712 23968973 8544586 9753968 ...
14 | $ male : num 59.3 75.1 73.8 50.9 74.1 72.7 71.6 80.9 79 69.6 ...
15 | $ female : num 61.9 80.7 77.5 54 78.6 79.9 77.7 84.8 83.9 75.8 ...
16 | $ lat : num 33.9 41.2 28 -11.2 17.1 ...
17 | $ lon : num 67.71 20.17 1.66 17.87 -61.8 ...
18 | ```
19 |
20 | ### Functionality
21 |
22 | * Tab datatable: displays the data and includes export options, show/hide columns
23 | * Tab Leaflet: displays the data on a map
24 | * Tab plotly: displays the data in a bar chart using the plotly library
25 | * Tab Contineous update: a plot that is updating every 2 sec using reactive timer
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Shiny tips and trics application
2 |
3 | This application contains functionality and patterns that I am using frequently using in my apps. You can view it live at
4 | [my website](http://www.gerinberg.com/shiny/shinytips)
5 |
6 | ### Functionality
7 |
8 | * A multi-tabbed application (base shiny)
9 | * Filtering of data through the use of sliders (base shiny)
10 | * CSS integration
11 | * Displaying and R-Markdown document
12 | * Displaying data in a table using DataTable package
13 | * Display data on a map with markers and circles using Leaflet package
14 | * Enabling/disabling components with shinyJS package
15 | * A simple login page
16 | * Download functionality
17 | * A contineous updating plot
18 | * [Google analytics](https://shiny.rstudio.com/articles/google-analytics.html)
19 | * Play an audio file
20 | * Busy indicator
21 |
22 | ### Data
23 |
24 | The dataset contains the life expectanncy of males and females in different countries in the world. It is based on babies that are born in 2015. I downloaded the dataset from
25 | [wikipedia](https://en.wikipedia.org/wiki/List_of_countries_by_life_expectancy)
26 |
27 | Please let me know if you have any questions or recommendations for improvement!
28 |
--------------------------------------------------------------------------------
/global.R:
--------------------------------------------------------------------------------
1 | library(shiny)
2 | library(shinyjs)
3 | library(leaflet)
4 | library(DT)
5 | library(ggplot2)
6 | library(plotly)
7 |
--------------------------------------------------------------------------------
/life_exp.csv:
--------------------------------------------------------------------------------
1 | country,region,population,male,female,lat,lon
2 | Afghanistan,Asia,32526562,59.3,61.9,33.93911,67.709953
3 | Albania,Europe,2896679,75.1,80.7,41.153332,20.168331
4 | Algeria,Africa,39666519,73.8,77.5,28.033886,1.659626
5 | Angola,Africa,25021974,50.9,54,-11.202692,17.873887
6 | Antigua and Barbuda,Americas,91818,74.1,78.6,17.060816,-61.796428
7 | Argentina,Americas,43416755,72.7,79.9,-38.416097,-63.616672
8 | Armenia,Asia,3017712,71.6,77.7,40.069099,45.038189
9 | Australia,Oceania,23968973,80.9,84.8,-25.274398,133.775136
10 | Austria,Europe,8544586,79,83.9,47.516231,14.550072
11 | Azerbaijan,Asia,9753968,69.6,75.8,40.143105,47.576927
12 | Bahamas,Americas,388019,72.9,79.1,25.03428,-77.39628
13 | Bahrain,Asia,1377237,76.2,77.9,26.0667,50.5577
14 | Bangladesh,Asia,160995642,70.6,73.1,23.684994,90.356331
15 | Barbados,Americas,284215,73.1,77.9,13.193887,-59.543198
16 | Belarus,Europe,9495826,66.5,78,53.709807,27.953389
17 | Belgium,Europe,11299192,78.6,83.5,50.503887,4.469936
18 | Belize,Americas,359287,67.5,73.1,17.189877,-88.49765
19 | Benin,Africa,10879829,58.8,61.1,9.30769,2.315834
20 | Bhutan,Asia,774830,69.5,70.1,27.514162,90.433601
21 | Bolivia,Americas,10724705,68.2,73.3,-16.290154,-63.588653
22 | Bosnia and Herzegovina,Europe,3810416,75,79.7,43.915886,17.679076
23 | Botswana,Africa,2262485,63.3,68.1,-22.328474,24.684866
24 | Brazil,Americas,207847528,71.4,78.7,-14.235004,-51.92528
25 | Bulgaria,Europe,7149787,71.1,78,42.733883,25.48583
26 | Burkina Faso,Africa,18105570,59.1,60.5,12.238333,-1.561593
27 | Burundi,Africa,11178921,57.7,61.6,-3.373056,29.918886
28 | Cabo Verde,Africa,520502,71.3,75,15.120142,-23.6051868
29 | Cambodia,Asia,15577899,66.6,70.7,12.565679,104.990963
30 | Cameroon,Africa,23344179,55.9,58.6,7.369722,12.354722
31 | Canada,Americas,35939927,80.2,84.1,56.130366,-106.346771
32 | Central African Republic,Africa,4900274,50.9,54.1,6.611111,20.939444
33 | Chad,Africa,14037472,51.7,54.5,15.454166,18.732207
34 | Chile,Americas,17948141,77.4,83.4,-35.675147,-71.542969
35 | China,Asia,1376048943,74.6,77.6,35.86166,104.195397
36 | Colombia,Americas,48228704,71.2,78.4,4.570868,-74.297333
37 | Comoros,Africa,788474,61.9,65.2,-11.6455,43.3333
38 | Congo,Africa,4620330,63.2,66.3,-4.038333,21.758664
39 | Costa Rica,Americas,4807850,77.1,82.2,9.748917,-83.753428
40 | Croatia,Europe,4240317,74.7,81.2,45.1,15.2
41 | Cuba,Americas,11389562,76.9,81.4,21.521757,-77.781167
42 | Cyprus,Asia,1165300,78.3,82.7,35.126413,33.429859
43 | Czech Republic,Europe,10543186,75.9,81.7,49.817492,15.472962
44 | Democratic Republic of the Congo,Africa,77266814,58.3,61.5,-4.038333,21.758664
45 | Denmark,Europe,5669081,78.6,82.5,56.26392,9.501785
46 | Djibouti,Africa,887861,61.8,65.3,11.825138,42.590275
47 | Dominican Republic,Americas,10528391,70.9,77.1,18.735693,-70.162651
48 | Ecuador,Americas,16144363,73.5,79,-1.831239,-78.183406
49 | Egypt,Africa,91508084,68.8,73.2,26.820553,30.802498
50 | El Salvador,Americas,6126583,68.8,77.9,13.794185,-88.89653
51 | Equatorial Guinea,Africa,845060,56.6,60,1.650801,10.267895
52 | Eritrea,Africa,5227791,62.4,67,15.179384,39.782334
53 | Estonia,Europe,1312558,72.7,82,58.595272,25.013607
54 | Ethiopia,Africa,99390750,62.8,66.8,9.145,40.489673
55 | Fiji,Oceania,892145,67,73.1,-17.713371,178.065032
56 | Finland,Europe,5503457,78.3,83.8,61.92411,25.748151
57 | France,Europe,64395345,79.4,85.4,46.227638,2.213749
58 | Gabon,Africa,1725292,64.7,67.2,-0.803689,11.609444
59 | Gambia,Africa,1990924,59.8,62.5,13.443182,-15.310139
60 | Georgia,Asia,3999812,70.3,78.3,32.1656221,-82.9000751
61 | Germany,Europe,80688545,78.7,83.4,51.165691,10.451526
62 | Ghana,Africa,27409893,61,63.9,7.946527,-1.023194
63 | Greece,Europe,10954617,78.3,83.6,39.074208,21.824312
64 | Grenada,Americas,106825,71.2,76.1,12.1165,-61.679
65 | Guatemala,Americas,16342897,68.5,75.2,15.783471,-90.230759
66 | Guinea,Africa,12608590,58.2,59.8,9.945587,-9.696645
67 | Guinea-Bissau,Africa,1844325,57.2,60.5,11.803749,-15.180413
68 | Guyana,Americas,767085,63.9,68.5,4.860416,-58.93018
69 | Haiti,Americas,10711067,61.5,65.5,18.971187,-72.285215
70 | Honduras,Americas,8075060,72.3,77,15.199999,-86.241905
71 | Hungary,Europe,9855023,72.3,79.1,47.162494,19.503304
72 | Iceland,Europe,329425,81.2,84.1,64.963051,-19.020835
73 | India,Asia,1311050527,66.9,69.9,20.593684,78.96288
74 | Indonesia,Asia,257563815,67.1,71.2,-0.789275,113.921327
75 | Iran,Asia,79109272,74.5,76.6,32.427908,53.688046
76 | Iraq,Asia,36423395,66.2,71.8,33.223191,43.679291
77 | Ireland,Europe,4688465,79.4,83.4,53.1423672,-7.6920536
78 | Israel,Asia,8064036,80.6,84.3,31.046051,34.851612
79 | Italy,Europe,59797685,80.5,84.8,41.87194,12.56738
80 | Jamaica,Americas,2793335,73.9,78.6,18.109581,-77.297508
81 | Japan,Asia,126573481,80.5,86.8,36.204824,138.252924
82 | Jordan,Asia,7594547,72.5,75.9,30.585164,36.238414
83 | Kazakhstan,Asia,17625226,65.7,74.7,48.019573,66.923684
84 | Kenya,Africa,46050302,61.1,65.8,-0.023559,37.906193
85 | Kiribati,Oceania,112423,63.7,68.8,1.8709422,-157.3628595
86 | Kuwait,Asia,3892115,73.7,76,29.31166,47.481766
87 | Kyrgyzstan,Asia,5939962,67.2,75.1,41.20438,74.766098
88 | Latvia,Europe,1970503,69.6,79.2,56.879635,24.603189
89 | Lebanon,Asia,5850743,73.5,76.5,33.854721,35.862285
90 | Lesotho,Africa,2135022,51.7,55.4,-29.609988,28.233608
91 | Liberia,Africa,4503438,59.8,62.9,6.428055,-9.429499
92 | Libya,Africa,6278438,70.1,75.6,26.3351,17.228331
93 | Lithuania,Europe,2878405,68.1,79.1,55.169438,23.881275
94 | Luxembourg,Europe,567110,79.8,84,49.815273,6.129583
95 | Madagascar,Africa,24235390,63.9,67,-18.766947,46.869107
96 | Malawi,Africa,17215232,56.7,59.9,-13.254308,34.301525
97 | Malaysia,Asia,30331007,72.7,77.3,4.210484,101.975766
98 | Maldives,Asia,363657,76.9,80.2,1.9772276,73.536101
99 | Mali,Africa,17599694,58.2,58.3,17.570692,-3.996166
100 | Malta,Europe,418670,79.7,83.7,35.937496,14.375416
101 | Mauritania,Africa,4067564,61.6,64.6,21.00789,-10.940835
102 | Mauritius,Africa,1273212,71.4,77.8,-20.348404,57.552152
103 | Mexico,Americas,127017224,73.9,79.5,23.634501,-102.552784
104 | Mongolia,Asia,2959134,64.7,73.2,46.862496,103.846656
105 | Montenegro,Europe,625781,74.1,78.1,42.708678,19.37439
106 | Morocco,Africa,34377511,73.3,75.4,31.791702,-7.09262
107 | Mozambique,Africa,27977863,55.7,59.4,-18.665695,35.529562
108 | Myanmar,Asia,53897154,64.6,68.5,21.916221,95.955974
109 | Namibia,Africa,2458830,63.1,68.3,-22.95764,18.49041
110 | Nepal,Asia,28513700,67.7,70.8,28.394857,84.124008
111 | Netherlands,Europe,16924929,80,83.6,52.132633,5.291266
112 | New Zealand,Oceania,4528526,80,83.3,-40.900557,174.885971
113 | Nicaragua,Americas,6082032,71.5,77.9,12.865416,-85.207229
114 | Niger,Africa,19899120,60.9,62.8,17.607789,8.081666
115 | Nigeria,Africa,182201962,53.4,55.6,9.081999,8.675277
116 | Norway,Europe,5210967,79.8,83.7,60.472024,8.468946
117 | Oman,Asia,4490541,75,79.2,21.4735329,55.975413
118 | Pakistan,Asia,188924874,65.5,67.5,30.375321,69.345116
119 | Panama,Americas,3929141,74.7,81.1,8.9823792,-79.5198696
120 | Papua New Guinea,Oceania,7619321,60.6,65.4,-6.314993,143.95555
121 | Paraguay,Americas,6639123,72.2,76,-23.442503,-58.443832
122 | Peru,Americas,31376670,73.1,78,-9.189967,-75.015152
123 | Philippines,Asia,100699395,65.3,72,12.879721,121.774017
124 | Poland,Europe,38611794,73.6,81.3,51.919438,19.145136
125 | Portugal,Europe,10349803,78.2,83.9,39.399872,-8.224454
126 | Qatar,Asia,2235355,77.4,80,25.354826,51.183884
127 | Romania,Europe,19511324,71.4,78.8,45.943161,24.96676
128 | Rwanda,Africa,11609666,60.9,71.1,-1.940278,29.873888
129 | Saint Lucia,Americas,184999,72.6,77.9,13.909444,-60.978893
130 | Saint Vincent and the Grenadines,Americas,109462,71.3,75.2,13.2528179,-61.1971628
131 | Samoa,Oceania,193228,70.9,77.5,-13.759029,-172.104629
132 | Sao Tome and Principe,Africa,190344,65.6,69.4,0.18636,6.613081
133 | Saudi Arabia,Asia,31540372,73.2,76,23.885942,45.079162
134 | Senegal,Africa,15129273,64.6,68.6,14.497401,-14.452362
135 | Serbia,Europe,8850975,72.9,78.4,44.016521,21.005859
136 | Seychelles,Africa,96471,69.1,78,-4.679574,55.491977
137 | Sierra Leone,Africa,6453184,49.3,50.8,8.460555,-11.779889
138 | Singapore,Asia,5603740,80,86.1,1.352083,103.819836
139 | Slovakia,Europe,5426258,72.9,80.2,48.669026,19.699024
140 | Slovenia,Europe,2067526,77.9,83.7,46.151241,14.995463
141 | Solomon Islands,Oceania,583591,67.9,70.8,-9.64571,160.156194
142 | Somalia,Africa,10787104,53.5,56.6,5.152149,46.199616
143 | South Africa,Africa,54490406,59.3,66.2,-30.559482,22.937506
144 | South Sudan,Africa,12339812,56.1,58.6,6.8769919,31.3069788
145 | Spain,Europe,46121699,80.1,85.5,40.463667,-3.74922
146 | Sri Lanka,Asia,20715010,71.6,78.3,7.873054,80.771797
147 | Sudan,Africa,40234882,62.4,65.9,12.862807,30.217636
148 | Suriname,Americas,542975,68.6,74.7,3.919305,-56.027783
149 | Swaziland,Africa,1286970,56.6,61.1,-26.522503,31.465866
150 | Sweden,Europe,9779426,80.7,84,60.128161,18.643501
151 | Switzerland,Europe,8298663,81.3,85.3,46.818188,8.227512
152 | Syrian Arab Republic,Asia,18502413,59.9,69.9,34.802075,38.996815
153 | Tajikistan,Asia,8481855,66.6,73.6,38.861034,71.276093
154 | Thailand,Asia,67959359,71.9,78,15.870032,100.992541
155 | Timor-Leste,Asia,1184765,66.6,70.1,-8.874217,125.727539
156 | Togo,Africa,7304578,58.6,61.1,8.619543,0.824782
157 | Tonga,Oceania,106170,70.6,76.4,-21.178986,-175.198242
158 | Trinidad and Tobago,Americas,1360088,67.9,74.8,10.691803,-61.222503
159 | Tunisia,Africa,11253554,73,77.8,33.886917,9.537499
160 | Turkey,Asia,78665830,72.6,78.9,38.963745,35.243322
161 | Turkmenistan,Asia,5373502,62.2,70.5,38.969719,59.556278
162 | Uganda,Africa,39032383,60.3,64.3,1.373333,32.290275
163 | Ukraine,Europe,44823765,66.3,76.1,48.379433,31.16558
164 | United Arab Emirates,Asia,9156963,76.4,78.6,23.424076,53.847818
165 | United Kingdom,Europe,64715810,79.4,83,55.378051,-3.435973
166 | Uruguay,Americas,3431555,73.3,80.4,-32.522779,-55.765835
167 | Uzbekistan,Asia,29893488,66.1,72.7,41.377491,64.585262
168 | Vanuatu,Oceania,264652,70.1,74,-15.376706,166.959158
169 | Venezuela,Americas,31108083,70,78.5,6.42375,-66.58973
170 | Yemen,Asia,26832215,64.3,67.2,15.552727,48.516388
171 | Zambia,Africa,16211767,59,64.7,-13.133897,27.849332
172 | Zimbabwe,Africa,15602751,59,62.3,-19.015438,29.154857
173 |
--------------------------------------------------------------------------------
/server.R:
--------------------------------------------------------------------------------
1 | source("global.R")
2 |
3 | credentials <- list("test" = "098f6bcd4621d373cade4e832627b4f6")
4 | ZOOM_LEVEL <- 3
5 |
6 | shinyServer(function(input, output, session) {
7 | source('ui.R') #login page
8 |
9 | USER <- reactiveValues(Logged = FALSE)
10 | INIT <- FALSE
11 |
12 | observeEvent(input$.login, {
13 |
14 | error <- FALSE
15 | user <- input$.username
16 | pwd <- input$.password
17 | if(user == "" | pwd == ""){
18 | error <- TRUE
19 | }
20 | if(!error){
21 | if (!is.null(credentials[[user]]) && credentials[[user]] == pwd){
22 | USER$Logged <- TRUE
23 | } else {
24 | error <- TRUE
25 | }
26 | }
27 | if(error){
28 | show("message")
29 | output$message = renderText("Invalid user name or password")
30 | delay(5000, hide("message", anim = TRUE, animType = "fade"))
31 | }
32 | })
33 |
34 | # Output the main content panel
35 | output$content = renderUI(
36 | ifelse(USER$Logged, uiNormal(), uiLogin())
37 | )
38 |
39 | # reactive expression for data
40 | data <- reactive({
41 | range_m <- input$life_exp_m
42 | range_f <- input$life_exp_f
43 | df_filtered <- df %>% filter(male >= range_m[1]) %>% filter(male <= range_m[2]) %>% filter(female >= range_f[1]) %>% filter(female <= range_f[2])
44 | return(df_filtered)
45 | })
46 |
47 | # map with locations of facilities
48 | output$map <- renderLeaflet({
49 | df <- data()
50 | if(nrow(df) > 0){
51 | leaflet() %>%
52 | addTiles() %>%
53 | setView(lng = df[1,]$lon, lat = df[1,]$lat, zoom = ZOOM_LEVEL) %>%
54 | addMarkers(data = df, lat = ~lat, lng = ~lon) %>%
55 | addCircles(data = df[1,], lng = ~lon, lat = ~lat, weight = 1, radius = ~(input$distance * 1000))
56 | }
57 | })
58 |
59 | # print content of data
60 | output$df_contents <- DT::renderDataTable(rownames = FALSE, extensions = 'Buttons',{
61 | df
62 | }, options = list(pageLength = 50,
63 | paging = TRUE,
64 | dom = 'Blfrtip',
65 | buttons = list('csv', 'print', 'pdf',
66 | list(extend = 'excel', exportOptions = list(columns = ':visible')),
67 | list(extend = 'colvis', text='Show/Hide Columns', collectionLayout='fixed two-column')
68 | )
69 | )
70 | )
71 |
72 | # plotly content
73 | output$plot <- renderPlotly({
74 | df <- data()
75 | m <- list(l = 150, r = 0, b = 150, t = 50, pad = 4)
76 | plot_ly(df, y = ~country, x = ~male, type = 'bar', name = 'Male') %>%
77 | add_trace(x = ~female, name = 'Female') %>%
78 | layout(title = "Life expectancy per country", yaxis = list(title = ''), xaxis = list(title = 'Age (years)'), barmode = 'group', margin = m)
79 | })
80 |
81 | observeEvent(input$showDataTab, {
82 | if(!INIT){
83 | show(selector = "a[data-value=DataTable]")
84 | INIT <<- TRUE
85 | } else{
86 | # switch tab if currently on data tab
87 | if (input$main == "DataTable"){
88 | updateTabsetPanel(session, inputId = 'main', selected = 'Leaflet')
89 | }
90 | toggle(selector = "a[data-value=DataTable]")
91 | }
92 | })
93 |
94 | # update the map markers and view on location selectInput changes
95 | observeEvent(c(input$location, input$distance), {
96 | proxy <- leafletProxy("map")
97 | if (nrow(df) > 0){
98 | # Add markers for chosen facility and the ones within chosen distance x
99 | df <- data()
100 | df_circle <- df[df$country == input$location,]
101 | proxy %>% clearShapes() %>% clearPopups() %>%
102 | addCircles(data = df_circle, lng = ~lon, lat = ~lat, weight = 1, radius = ~(input$distance * 1000)) %>%
103 | setView(lng = df_circle[1,'lon'], lat = df_circle[1,'lat'], zoom = ZOOM_LEVEL) # update the center of the map with the location of the selected facility (use current zoom level)
104 | }
105 | })
106 |
107 | # When map is clicked, show a popup with info
108 | observeEvent(input$map_marker_click, {
109 | event <- input$map_marker_click
110 | loc <- df[df$lat == as.numeric(event$lat) & df$lon == as.numeric(event$lng),]
111 | content <- paste("Country:", loc$country, "
", "Male:", loc$male, "
", "Female:", loc$female)
112 | leafletProxy("map") %>% clearPopups() %>% addPopups(event$lng, event$lat, content, layerId = event$id)
113 | })
114 |
115 | # when sliders are changed, update dropdown
116 | observeEvent(c(input$life_exp_f, input$life_exp_m), {
117 | updateSelectInput(session, "location", choices = data()$country)
118 | })
119 |
120 | # Reactive timer
121 | autoInvalidate <- reactiveTimer(3000)
122 |
123 | # Generate a new histogram each time the timer fires
124 | output$contPlot <- renderPlot({
125 | autoInvalidate()
126 | hist(rnorm(10), xlab = "Value", main = "Histogram of a random normal distribution with 10 observations")
127 | })
128 |
129 | observeEvent(input$playSound, {
130 | disable("playSound")
131 | js$playMusic()
132 | })
133 | observeEvent(input$stopSound, {
134 | enable("playSound")
135 | js$stopMusic()
136 | })
137 | observeEvent(input$showProgress, {
138 | Sys.sleep(5)
139 | })
140 |
141 | })
--------------------------------------------------------------------------------
/ui.R:
--------------------------------------------------------------------------------
1 | source("global.R")
2 |
3 | df <- read.csv("life_exp.csv", stringsAsFactors = FALSE)
4 |
5 | uiLogin <- function(req){
6 | tagList(
7 | fluidRow(
8 | column(12,
9 | fluidRow(column(width=6, offset = 3,
10 | div(
11 | HTML("
This shiny app contains some tips and tricks that you can use in your application. Most of these are solutions I am frequently using in my apps. It contains: 12 |
13 |