There and Back Again competition entry https://shiny.petras.space/commute/
rstats
rshiny
census
competition
leaflet
javascript
stats-nz

app.R 7.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. library(shiny)
  2. library(shinyjs)
  3. library(leaflet)
  4. library(rgdal)
  5. library(dplyr)
  6. library(leaflet.extras)
  7. source("leafletfunctions.R")
  8. # work_travel <- read_csv("../travel-work.csv")
  9. load(file="datasets.RData")
  10. shpf <- readOGR(dsn="../shapefiles/sa20025WGSfilcth")
  11. sa.in.dest <- shpf@data$SA22018_V1 %in% work_to$work_code
  12. sa.in.home <- shpf@data$SA22018_V1 %in% work_from$res_code
  13. transport.t <- c("Work at home", "Private car", "Company car",
  14. "Carpool", "Bus", "Train", "Bicycle", "Walk",
  15. "Ferry", "Other", "None")
  16. cols.labs <- c(transport.t[1:10], "Total")
  17. codelist <- shpf@data %>%
  18. mutate(sa2_code = as.numeric(as.character(SA22018_V1))) %>%
  19. select(sa2_code)
  20. startcols.res <- codelist %>% left_join(work_from, by = c("sa2_code" = "res_code"))
  21. startcols.res <- tencols[startcols.res$MAX]
  22. startcols.res <- ifelse(is.na(startcols.res), "#808080", startcols.res)
  23. startcols.work <- codelist %>% left_join(work_to, by = c("sa2_code" = "work_code"))
  24. startcols.work <- tencols[startcols.work$MAX]
  25. startcols.work <- ifelse(is.na(startcols.work), "#808080", startcols.work)
  26. # Define UI
  27. ui <- fluidPage(
  28. useShinyjs(),
  29. leafletjs,
  30. tags$style(type = "text/css",
  31. "html, body {
  32. width:100%;
  33. height:100%
  34. }
  35. #map {
  36. height: 100% !important;
  37. position: absolute !important;
  38. top: 0;
  39. left: 0;
  40. }
  41. #loading {
  42. cursor: progress !important;
  43. }
  44. #loading p {
  45. border-radius: 5px;
  46. background-color: rgba(255, 255, 255, 0.8);
  47. padding: 6px 8px;
  48. box-shadow: 0 0 15px rgba(0,0,0,0.2);
  49. font-size: 1.5em;
  50. font-weight: bold;
  51. }
  52. #mapcontrol {
  53. background-color: rgba(255, 255, 255, 0.8);
  54. border-radius: 5px;
  55. box-shadow: 0 0 15px rgba(0,0,0,0.2);
  56. padding: 6px 8px;
  57. font: 14px/16px Arial, Helvetica, sans-serif;
  58. }
  59. #lochtml ul {
  60. padding-left: 15px;
  61. }"),
  62. leafletOutput("map"),
  63. absolutePanel(top = 10, right = 10, id="mapcontrol",
  64. radioButtons("radioinout", label="Show commuters who",
  65. choices = c(
  66. "Live in area" = "res",
  67. "Work in area" = "work"
  68. ),
  69. inline = FALSE),
  70. radioButtons("radiocolour",
  71. label = "Colour by",
  72. choices = c(
  73. "Transport type" = "type",
  74. "Number of commuters" = "number"
  75. ),
  76. inline = FALSE),
  77. div(id="locinfo",
  78. htmlOutput("lochtml"))),
  79. absolutePanel(bottom = 30, left = 30, id="loading",
  80. p("Loading..."))
  81. )
  82. # Define server logic
  83. server <- function(input, output) {
  84. sel.SA2.code <- reactiveVal(0)
  85. p.layers <- c("polya", "polyb")
  86. output$map <- renderLeaflet({
  87. leaf <- leaflet(shpf, options = leafletOptions(minZoom = 3, maxZoom = 13)) %>%
  88. addPolygons(color="#000", opacity = 1, weight=1,
  89. fillColor = startcols.res,
  90. layerId = ~SA22018_V1,
  91. label = shpf@data$SA22018__1,
  92. fillOpacity = 1) %>%
  93. setView(174, -41, 5) %>%
  94. addResetMapButton() %>%
  95. addLegend(position = "topleft",
  96. colors = c(tencols, "#808080"),
  97. labels = transport.t, opacity = 1)
  98. shinyjs::hideElement(selector="#loading p", asis = TRUE,
  99. anim=TRUE, animType = "slide", time=7)
  100. leaf
  101. })
  102. updateMap <- function() {
  103. shinyjs::showElement(selector="#loading p", asis = TRUE,
  104. anim=TRUE, animType = "slide")
  105. selcode <- sel.SA2.code()
  106. selcode <- ifelse(is.na(selcode), 0, selcode)
  107. if (input$radioinout == "work") {
  108. fcols <- startcols.work
  109. if (selcode != 0) {
  110. codvs <- work_simp %>% filter(work_code == selcode)
  111. codvs <- codelist %>% left_join(codvs, by=c("sa2_code" = "res_code"))
  112. codvs <- tencols[codvs$MAX]
  113. fcols <- ifelse(is.na(codvs), "#808080", codvs)
  114. }
  115. } else {
  116. fcols <- startcols.res
  117. if (selcode != 0) {
  118. codvs <- work_simp %>% filter(res_code == selcode)
  119. codvs <- codelist %>% left_join(codvs, by=c("sa2_code" = "work_code"))
  120. codvs <- tencols[codvs$MAX]
  121. fcols <- ifelse(is.na(codvs), "#808080", codvs)
  122. }
  123. }
  124. lp <- leafletProxy("map", data = shpf) %>%
  125. setShapeStyle(layerId = ~SA22018_V1, fillColor = fcols) %>%
  126. clearControls() %>%
  127. addLegend(position = "topleft",
  128. colors = c(tencols, "#808080"),
  129. labels = transport.t, opacity = 1) %>%
  130. clearGroup("hpoly")
  131. if (selcode %in% shpf@data$SA22018_V1) {
  132. lp %>% addPolygons(group = "hpoly",
  133. weight = 4,
  134. data = shpf[which(shpf@data$SA22018_V1 == selcode),],
  135. color = "#000000",
  136. fill = FALSE, opacity = 1)
  137. }
  138. shinyjs::hideElement(selector="#loading p", asis=TRUE,
  139. anim=TRUE, animType = "slide",
  140. time = 1)
  141. }
  142. observeEvent(input$map_shape_click, ignoreInit = TRUE, {
  143. p <- input$map_shape_click
  144. pdat <- data.frame(Longitude = p$lng,
  145. Latitude =p$lat)
  146. coordinates(pdat) <- ~ Longitude + Latitude
  147. proj4string(pdat) <- proj4string(shpf)
  148. ppoly <- over(pdat, shpf)
  149. codetmp <- as.numeric(as.character(ppoly[1,"SA22018_V1"]))
  150. codetmp <- ifelse(is.na(codetmp), 0, codetmp)
  151. sel.SA2.code(ifelse(sel.SA2.code() == codetmp, 0, codetmp))
  152. updateMap()
  153. })
  154. observeEvent(input$radioinout, ignoreInit = TRUE, {
  155. updateMap()
  156. })
  157. output$lochtml <- renderUI({
  158. seled <- sel.SA2.code()
  159. seled <- ifelse(is.na(seled), 0, seled)
  160. if (seled == 0) {
  161. HTML("")
  162. } else {
  163. hrstr <- "<hr style='border-top: 1px solid #000;'/>"
  164. str <- sprintf("<b>%s</b>",
  165. shpf@data$SA22018__1[shpf@data$SA22018_V1 == seled])
  166. if (input$radioinout == "work") {
  167. str <- sprintf("<p>Commuting method of people who <b>work</b> in</p>
  168. <p><b><u>%s</u></b></p>", str)
  169. vals <- as.numeric(work_to[work_to$work_code == seled, 5:15])
  170. vals <- ifelse(is.na(vals), 0, vals)
  171. vals <- ifelse(vals < 0, "~0", as.character(vals))
  172. listi <- paste0(sprintf("<li>%s: %s</li>", cols.labs,
  173. vals),
  174. collapse="")
  175. str <- paste0(hrstr, str, "<ul>", listi, "</ul>")
  176. } else {
  177. str <- sprintf("<p>Commuting method of people who <b>live</b> in</p>
  178. <p><b><u>%s</u></b></p>", str)
  179. vals <- as.numeric(work_from[work_from$res_code == seled, 5:15])
  180. vals <- ifelse(is.na(vals), 0, vals)
  181. vals <- ifelse(vals < 0, "~0", as.character(vals))
  182. listi <- paste0(sprintf("<li>%s: %s</li>", cols.labs,
  183. vals),
  184. collapse="")
  185. str <- paste0(hrstr, str, "<ul>", listi, "</ul>")
  186. }
  187. HTML(str)
  188. }
  189. })
  190. }
  191. # Run the application
  192. shinyApp(ui = ui, server = server)