Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shiny reactive #35

Merged
merged 11 commits into from
Nov 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,18 @@ Depends:
R (>= 3.6.0)
Imports:
colourvalues,
ggplot2,
shiny (>= 1.3.2),
leaflet (>= 2.0.2),
sf (>= 0.7.6),
tmap (>= 2.3),
mapdeck (>= 0.2.1)
Suggests:
knitr,
rmarkdown,
tmap
Remotes:
SymbolixAU/geojsonsf,
SymbolixAU/spatialwidget,
SymbolixAU/mapdeck
RoxygenNote: 6.1.1
Suggests:
knitr,
rmarkdown
RoxygenNote: 7.0.1
VignetteBuilder: knitr
1 change: 0 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@ export(shinyAppServer)
export(shinyAppUI)
import(leaflet)
import(shiny)
import(tmap)
importFrom(graphics,hist)
112 changes: 112 additions & 0 deletions R/health-calculations.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Average global mortality from WHO database
get_mortality = function() {
#x = read.csv("../who3/health-econ/who-mortality.csv")
#names(x) = c("country", "population", "deaths", "remove")
#x$remove = NULL
#x = x [!is.na(x$deaths), ]
#mortality = mean(x$deaths / x$population)
0.007425708
}

# Mode shift response based entirely on Accra walking statistics
mode_shift_response = function(mode_incr = 0.01, city_pop, mortality) {
# Accra data for distance walked to market
d_market = c(0.5, 1.5, 2.5, 4.5, 8.5)
p_market = c(0.273, 0.212, 0.061, 0.424, 0.03)
d_market = sum(d_market * p_market)

# Accra data for distance walked to trotro
d_tro = c(0.25, 0.75, 1.5, 3.5, 7.5)
p_tro = c(0.832, 0.119, 0.023, 0.005, 0.022)
d_tro = sum(d_tro * p_tro)

# Estimate of distance walked to work based on relative frequencies of trips
# # to market and trotro
d_work = (0.474 * d_market + 0.19 * d_tro) / (0.474 + 0.19)

# Accra data for numbers of weekly walking trips
n_walk = c(5, 15.5, 25.5, 35.5, 50.5, 80.5)
p_walk = c(0.64, 0.204, 0.062, 0.029, 0.034, 0.007)
n_walk = 7 * sum(n_walk * p_walk)

# Reference weekly walking distance
d_walk_ref = (n_walk - 5) * d_tro + 2.5 * 0.474 * d_work + 2.5 * d_market

# Change in daily distance walked to work in response to mode_incr for
# walking
d_work = ((0.474 * (1 + mode_incr)) * d_market +
(0.19 * (1 + mode_incr)) * d_tro) / (0.474 + 0.19)
# Change in daily distance walked in general in response to mode_incr for
# walking
d_walk = (n_walk - 5) * (1 + mode_incr) * d_tro +
2.5 * 0.474 * (1 + mode_incr) * d_work +
2.5 * (1 + mode_incr) * d_market

# Overall risk ratio for change in distance walked:
rr = 0.114 * d_walk / d_walk_ref - 0.114
mortality_here = city_pop * mortality * rr
data.frame(mode_shift = mode_incr,
dist_ref = d_walk_ref,
dist = d_walk,
increase = d_walk / d_walk_ref - 1,
rr = rr,
d_mortality = mortality_here)
}

get_scenario_results = function(city = "Accra", has_tram = FALSE) {
nm = "scenario-results-table.csv"
f = system.file(nm, package = "upthat")
if(f == "") {
u = paste0 ("https://github.com/ATFutures/upthat/releases/",
"download/0.0.2/", nm)
path = dirname(system.file("net.Rds", package = "upthat"))
utils::download.file(u, destfile = file.path(path, nm))
f = system.file(nm, package = "upthat")
}
mode_shift = utils::read.csv(f)
mode_shift [tolower(mode_shift$City) == tolower(city) &
mode_shift$has_tram == has_tram, ]
}

get_population = function(city) {
switch(city,
"Accra" = 2.27e6,
"Kathmandu" = 1.74e6)
}


calc_exposure = function(city = "Accra", has_tram = FALSE) {
# Assume fixed PM2.5 values as for Accra
pm25bg = 35
pm25max = 50

mode_shift = get_scenario_results(city = city, has_tram = has_tram)

# pm25bg modified by reduction in car usage due to mode shift:
car_red = mode_shift$car / 100
pm25bg_mod = pm25bg + car_red * (pm25max - pm25bg) / pm25bg
# presume average walking concentrations half way to max value:
pm25walk = (pm25max + pm25bg_mod) / 2

response = mode_shift_response(mode_incr = mode_shift$walking / 100,
city_pop = get_population(city),
mortality = get_mortality())

mode_shift = cbind(mode_shift, response [, -1])

# average weekly concentration for reference case:
walk_time = response$dist_ref / 5.3
non_walk_time = 24 * 7 - walk_time
pm25_ref = (pm25bg_mod * non_walk_time + pm25walk * walk_time) / (24 * 7)

# modified average weekly concentration for scenario
walk_time = response$dist / 5.3
non_walk_time = 24 * 7 - walk_time
pm25_scenario = (pm25bg_mod * non_walk_time + pm25walk * walk_time) / (24 * 7)
# capped at 50, but all well below here, so can be left as is

d_exposure = pm25_scenario - pm25_ref
mode_shift$exposure = get_population(city) *
get_mortality() * d_exposure * 0.07 / 10
return(mode_shift)
}
37 changes: 30 additions & 7 deletions R/server.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
#' @param output provided by shiny
#' @param session The shiny session

#' @import leaflet
#' @import tmap
#' @export
# Define server logic required to draw a histogram
shinyAppServer = function(input, output, session) {
Expand Down Expand Up @@ -38,6 +36,9 @@ shinyAppServer = function(input, output, session) {
"Found these Rds files: ",
paste0(rds_files_available, collapse = ", ")
)

ggplot2::theme_set(ggplot2::theme_minimal())

output$mymap = mapdeck::renderMapdeck({
mapdeck::mapdeck(style = "mapbox://styles/mapbox/light-v10")
})
Expand All @@ -59,7 +60,7 @@ shinyAppServer = function(input, output, session) {
message("Reading this matching file: ", matching_file)
net <<- readRDS(matching_file)
net$layer = net$flow
plot_layer(net, input$layer, update_view = TRUE)
plot_map(net, input$layer, update_view = TRUE)
}
)

Expand All @@ -77,7 +78,7 @@ shinyAppServer = function(input, output, session) {
net$layer = net$flow
}
}
plot_layer(net, input$layer, update_view = FALSE)
plot_map(net, input$layer, update_view = FALSE)
}
)

Expand All @@ -93,14 +94,23 @@ shinyAppServer = function(input, output, session) {
net$layer = net$flow
}
}
plot_layer(net, input$layer, update_view = TRUE)
plot_map(net, input$layer, update_view = TRUE)
}
)

x = reactive({
g = plot_chart(city = input$city_sc)
return(g)
})
output$plot = renderPlot({
print(x())
})

}

plot_layer = function(net, leg_title, update_view = FALSE) {
plot_map = function(net, leg_title, update_view = FALSE) {
net$width = 100 * net$layer / max(net$layer, na.rm = TRUE)
cols = rgb(colourvalues::get_palette("inferno"), maxColorValue = 255)
cols = grDevices::rgb(colourvalues::get_palette("inferno"), maxColorValue = 255)
variables = seq(min(net$layer), max(net$layer), length.out = 5)
if (variables [1] < 1e-6) {
variables [1] = 0
Expand All @@ -126,3 +136,16 @@ plot_layer = function(net, leg_title, update_view = FALSE) {
layer_id = "mylayer"
)
}

plot_chart = function(city) {
x = calc_exposure(city = city, has_tram = FALSE)
x$mortality_reduction = x$d_mortality - x$exposure
# suppress no visible binding notes:
bus_stops_per_1000 = mortality_reduction = NULL
ggplot2::ggplot(x, ggplot2::aes(x = bus_stops_per_1000,
y = mortality_reduction)) +
ggplot2::geom_point() +
ggplot2::geom_line() +
ggplot2::geom_smooth(method = "lm") +
ggplot2::theme(axis.title.y = ggplot2::element_text(angle = 90))
}
37 changes: 23 additions & 14 deletions R/ui.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,28 @@
#' @import shiny
#' @import leaflet
#' @export
shinyAppUI = fluidPage(
shiny::titlePanel("Urban Planning and Transport Health Assessment Tool (upthat)"),
column(12, shiny::htmlOutput("app_info")),
column(width = 3,
selectInput("city", label = "City", choices = c("Accra", "Kathmandu", "Bristol", "NYC")),
selectInput("mode", label = "Mode of transport", choices = c("Walk", "Cycle", "Ebike", "Escooter", "Fly")),
selectInput("layer", label = "Layer", choices = c("pedestrian flow", "exposure")),
sliderInput("bus", "Number of bus stops added per 1,000", min = 0, max = 10, value = 1),
sliderInput("obs", "Investment (US $ millions):", min = 0, max = 50, value = 0.5, step = 0.1)
shinyAppUI = navbarPage("Urban Planning and Transport Health Assessment Tool (upthat)",
tabPanel("Maps",
column(12, shiny::htmlOutput("app_info")),
column(width = 3,
selectInput("city", label = "City", choices = c("Accra", "Kathmandu", "Bristol", "NYC")),
selectInput("mode", label = "Mode of transport", choices = c("Walk", "Cycle", "Ebike", "Escooter", "Fly")),
selectInput("layer", label = "Layer", choices = c("pedestrian flow", "exposure")),
sliderInput("bus", "Number of bus stops added per 1,000", min = 0, max = 10, value = 1),
sliderInput("obs", "Investment (US $ millions):", min = 0, max = 50, value = 0.5, step = 0.1)
),
column(width = 9,
mapdeck::mapdeckOutput ("mymap")
),
p(),
actionButton("recalc", "Zoom to city extent")
),
column(width = 9,
mapdeck::mapdeckOutput ("mymap")
),
p(),
actionButton("recalc", "Zoom to city extent")
tabPanel("Health Impacts",
column(width=3,
selectInput("city_sc", label = "City", choices = c("Accra", "Kathmandu", "Bristol", "NYC"))
),
column(width=9,
plotOutput("plot")
)
)
)