-
Notifications
You must be signed in to change notification settings - Fork 7
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
[Feature Request]: Box plots #70
Comments
Hi Rick, You're right - while we currently only support the seven openair directional analysis plots (polar plots, polar annuli, wind roses, etc.) we could in principle use any plot type. All openairmaps does "under the hood" is save the plot images to a temporary directory and then use them as marker images. In fact, I have a blog post outlining how to do this exact thing: https://jack-davison.github.io/posts/2023-09-26-ILL-PlotMarkers/ The current suite of plots lend themselves to being used as map markers because they are directional in nature - so allow for things like triangulating sources. But it could be on the cards to have other plot types like boxplots to facilitate easy comparisons between measured concentrations at different sensors. I think my preference would be for relatively simple graphics (like those of https://github.com/rte-antares-rpackage/leaflet.minicharts) - using a whole timeVariation plot as a marker may end up looking too busy. Will give this some thought and happy to hear any ideas! |
Example mock-up below. It's very possible. Some notes:
library(openairmaps)
library(openair)
library(leaflet)
library(tidyverse)
# arbitrary postcode
latlng <- convertPostcode("SW1A 1AA")
# get codes near postcode
codes <-
searchNetwork(
lat = latlng$lat,
lng = latlng$lng,
n = 10,
map = FALSE,
year = 2018
)
# import data
aq <- importUKAQ(codes$code, year = 2018, meta = TRUE)
# pivot longer
aq_long <-
aq |>
select(site, code, date, no2, pm10, pm2.5, o3, latitude, longitude) |>
pivot_longer(no2:o3)
# nest
aq_nested <-
nest_by(aq_long, site, code, latitude, longitude)
# get a colour palette
vars <- unique(aq_long$name)
cols <- setNames(openair::openColours(scheme = "Spectral", n = length(vars)), vars)
# work out the ymax of boxplots w/out outliers
gg <-
aq_long |>
ggplot(aes(x = name, y = value, color = site)) +
geom_boxplot(outliers = FALSE)
ymax <- max(pretty(ggplot_build(gg)$data[[1]]$ymax))
# function to construct boxplots
make_boxplot <- function(data, ymax) {
data |>
ggplot(aes(x = name, y = value)) +
geom_crossbar(
data = distinct(data, name),
aes(
xmin = name,
xmax = name,
ymin = 0,
ymax = 0,
y = 0
),
linewidth = 0.1
) +
geom_boxplot(na.rm = TRUE,
aes(fill = name, color = name),
alpha = 0.5,
outliers = FALSE,
linewidth = 0.5) +
theme_void() +
theme(legend.position = "none", aspect.ratio = 1) +
scale_color_manual(values = cols, aesthetics = c("fill", "color")) +
scale_y_continuous(limits = c(0, ymax))
}
# temporary directory to save plots
t <- tempdir()
# create plots & urls
plots <-
aq_nested |>
mutate(plot = list(make_boxplot(data, ymax)),
url = paste0(t, "/", latitude, "_", longitude, ".png"))
# save plots
purrr::walk2(.x = plots$plot,
.y = plots$url,
.progress = TRUE,
.f = ~ {
ggsave(
filename = .y,
plot = .x,
width = 1,
height = 1,
dpi = 300,
bg = "transparent"
)
})
# make leaflet map
leaflet(plots) |>
addProviderTiles(providers$CartoDB.PositronNoLabels) |>
addMarkers(icon = ~ makeIcon(url, iconWidth = 75, iconHeight = 75),
label = ~ site) |>
addLegend(colors = cols,
labels = quickTextHTML(names(cols)),
title = "Pollutant") |
yes, this is just what I was asking about! And I fully recognize that this could become really complicated really quickly if you used complex data viz outputs as your markers (like the full timeVariation() output - which would be a true chartjunk). But we often use these outputs as infographics to disseminate data to a community, so being able to do so natively would be really powerful. Thanks! |
I think we're on the same page, then! I've just released a new version of |
Wonder how difficult it would be implement boxplots on maps, similar to what you already produce, but limited to polarPlots. For example, one might have a network of monitors across a region, and may wish to plot annual mean concentrations by year, and/or perhaps an all-year site mean concentration; and do this at several sites across a city. For that matter, I suppose one could call any of the openair or ggplot functions like timeVariation, timePlot, etc.
The text was updated successfully, but these errors were encountered: