simplevis

David Hodge

2020-04-22

library(simplevis)
library(dplyr)

Making simplevis ggplot graphs

simplevis provides the following types of ggplot graph:

For each graph type 4 functions are available.

  1. A ggplot not coloured or faceted (e.g. gglot_hbar)
plot_data <- ggplot2::diamonds %>%
  mutate(cut = stringr::str_to_sentence(cut)) %>%
  group_by(cut) %>%
  summarise(average_price = mean(price)) %>%
  ungroup() %>% 
  mutate(average_price_thousands = round(average_price / 1000, 1)) %>%
  mutate(cut = factor(cut, levels = c("Fair", "Good", "Very good", "Premium", "Ideal"))) 

plot <- ggplot_hbar(data = plot_data, 
                    x_var = average_price_thousands, 
                    y_var = cut,
                    title = "Average diamond price by cut", 
                    x_title = "Average price ($US thousands)", 
                    y_title = "Cut")

plot 

  1. A ggplot coloured, but not faceted (e.g. gglot_hbar_col)
plot_data <- ggplot2::diamonds %>%
  mutate(cut = stringr::str_to_sentence(cut)) %>%
  group_by(cut, clarity) %>%
  summarise(average_price = mean(price)) %>%
  mutate(average_price_thousands = round(average_price / 1000, 1)) %>%
  ungroup()

plot <- ggplot_hbar_col(data = plot_data, 
                        x_var = average_price_thousands, 
                        y_var = cut, 
                        col_var = clarity, 
                        legend_ncol = 4)

plot

  1. A ggplot facetted, but not coloured (e.g. gglot_hbar_facet)
plot_data <- ggplot2::diamonds %>%
  mutate(cut = stringr::str_to_sentence(cut)) %>%
  group_by(cut, clarity) %>%
  summarise(average_price = mean(price)) %>%
  mutate(average_price_thousands = round(average_price / 1000, 1)) %>%
  ungroup()

plot <- ggplot_hbar_facet(data = plot_data, 
                          x_var = average_price_thousands, 
                          y_var = cut, 
                          facet_var = clarity)

plot

  1. A ggplot coloured and facetted (e.g. gglot_hbar_col_facet)
plot_data <- ggplot2::diamonds %>%
  mutate(cut = stringr::str_to_sentence(cut)) %>%
  group_by(cut, clarity, color) %>%
  summarise(average_price = mean(price)) %>%
  mutate(average_price_thousands = round(average_price / 1000, 1)) %>%
  ungroup()

plot <- ggplot_hbar_col_facet(data = plot_data, 
                              x_var = average_price_thousands, 
                              y_var = color, 
                              col_var = clarity, 
                              facet_var = cut,
                              legend_ncol = 4)

plot

These ggplot graphs have been designed that users can convert them easily to html interactive objects by wrapping them in plotly::gglotly with the tooltip = "text" specification. This results in the tooltip converting the applicable variable name to sentence case and replacing underscores with spaces.

plot_data <- storms %>%
  group_by(year) %>%
  summarise(average_wind = round(mean(wind), 2)) %>%
  ungroup()

plot <- ggplot_vbar(data = plot_data, 
                    x_var = year, 
                    y_var = average_wind, 
                    title = "Average wind speed of Atlantic storms, 1975\u20132015",
                    x_title = "Year",
                    y_title = "Average maximum sustained wind speed (knots)")

plotly::ggplotly(plot, tooltip = "text") %>%
      plotly::config(displayModeBar = F)

Making simplevis ggplot maps

simplevis provides the following types of ggplot map:

Simple feature (sf) maps are maps of points, lines or polygons.

The following functions are available:

These functions work in the same way as the ggplot graph functions, but with the following key differences:

map_data <- example_sf_nz_river_wq %>%
  dplyr::filter(period == "1998-2017", indicator == "Nitrate-nitrogen") 

ggplot_sf(data = map_data, 
          coastline = nz, 
          size = 0.25)

map_data <- example_sf_nz_river_wq %>%
  filter(period == "1998-2017", indicator == "Nitrate-nitrogen") 

pal <- c("#4575B4", "#D3D3D3", "#D73027")

ggplot_sf_col(data = map_data, 
              col_var = trend_category, 
              coastline = nz, 
              size = 0.25, 
              pal = pal, 
              title = "Monitored river nitrate-nitrogen trends, 2008\u201317")

map_data <- example_sf_nz_river_wq %>%
 filter(period == "1998-2017", indicator == "Nitrate-nitrogen") 

ggplot_sf_facet(data = map_data, 
                facet_var = trend_category, 
                coastline = nz, 
                size = 0.25,
                title = "Monitored river nitrate-nitrogen trends, 2008\u201317")

map_data <- example_sf_nz_river_wq %>%
 filter(period == "1998-2017", indicator %in% c("Nitrate-nitrogen", "Dissolved reactive phosphorus")) 

pal <- c("#4575B4", "#D3D3D3", "#D73027")

ggplot_sf_col_facet(data = map_data, 
                    col_var = trend_category, 
                    facet_var = indicator,
                    coastline = nz, 
                    size = 0.25, 
                    pal = pal,
                    title = "Monitored river nitrate-nitrogen trends, 2008\u201317")

simplevis provides ggplot maps made for spatial temporal arrays (stars).

The following functions are available:

These functions work in the same way as the ggplot sf map functions, but with the following key differences:

ggplot_stars_col(data = example_stars_nz_no3n, 
                 coastline = nz,
                 col_method = "quantile", 
                 title = "River modelled median nitrate-nitrogen concentrations, 2013\u201317",
                 legend_digits = 1)

map_data1 <- example_stars_nz_no3n %>%
  rlang::set_names("Nitrate nitrogen")

map_data2 <- example_stars_nz_drp %>%
  rlang::set_names("Dissolved reactive phosphorus")

map_data <- c(map_data1, map_data2)

ggplot_stars_col_facet(data = map_data, 
                       coastline = nz,
                       title = "River modelled nutrient concentrations, 2013\u201317")

Making simplevis leaflet maps

simplevis provides the following types of leaflet map:

These work in the same way as the ggplot map functions, but with no coastline arguments.

Outputs are hidden to keep the size of the vignette manageable.

leaflet_sf(data = example_sf_nz_livestock)
map_data <- example_sf_nz_livestock %>%
  mutate(dairydens = round(dairydens, 2))

leaflet_sf_col(data = map_data, 
               col_var = dairydens, 
               col_method = "bin", 
               bin_cuts = c(0, 10, 50, 100, 150, 200, Inf), 
               legend_digits = 0,
               title = "Dairy density in count per km\u00b2, 2017")
leaflet_stars_col(data = example_stars_nz_no3n,
   title = "River modelled median nitrate-nitrogen concentrations in g/m\u00b3, 2013\u201317")

Working with quoted variable inputs

simplevis can also work with quoted variable inputs. The user must place each quoted variable within a simplevis function within a !!sym function, as per the example below. This can be helpful, particularly when working in shiny apps.

plot_data <- ggplot2::diamonds %>%
  mutate_at(vars("cut"), ~stringr::str_to_sentence(.)) %>%
  group_by_at(vars("cut")) %>%
  summarise_at(vars("price"), ~mean(.)) %>%
  ungroup() %>% 
  mutate_at(vars("price"), ~round(. / 1000, 2)) %>%
  mutate_at(vars("cut"), ~factor(., levels = c("Fair", "Good", "Very good", "Premium", "Ideal"))) 

x_var <- "price"
y_var <- "cut"

plot <- ggplot_hbar(data = plot_data, 
                    x_var = !!sym(x_var), 
                    y_var = !!sym(y_var),
                    title = "Average diamond price by cut", 
                    x_title = "Average price ($US thousands)", 
                    y_title = "Cut")

plot 

Making shiny apps with simplevis

simplevis provides three template shiny apps and three example apps showing how to apply each of these templates. Templates are called template1, template2 and template3, and examples showing application of each of these called example1, example2 and example3. Users can access these functions by using the run_template and run_example functions for the applicable app, and then clicking on the download_code button to access a zip file of the code. It is intended that users download the applicable template and example, and refer to both to understand how the code works.

run_template("template1") # a graph and table
run_template("template2") # a leaflet map, as well as graph and table
run_template("template3") # a dual leaflet map, as well as graph and table

run_example("example1") # example application of template1
run_example("example2") # example application of template2
run_example("example3") # example application of template3

For a simple graph app, the basic method to create an app is:

Mobile compliance - ggplotly for desktop and ggplot for mobile

The template apps have a function with javascript in it that provides a TRUE or FALSE values if the user is on a mobile device. This can value can be referred to in the server code as input$isMobile. This is using the method developed by Gervasio Marchand.

The simplevis ggplot functions have a isMobile specification with values of TRUE or FALSE for whether the user is on a mobile device or not. When isMobile equals TRUE, titles, legend elements, and facets are wrapped accordingly for the smaller screen size. Therefore, when simplevis ggplot functions are used within shiny, the app developer must specify isMobile = input$isMobile within the simplevis ggplot function.

ggplotly has a bug that it is currently not able to convert a ggplot object with a legend on the bottom to html. This causes ggplotly graphs not to be able to display well currently on a mobile. It is possible to add the legend in manually with a plotly argument to the ggplotly object. However, this causes positioning issues between the x axis title and the legend, with the two often overlapping.

As such, the safest option to ensuring that a graph diplays well on a mobile device is to render it as a ggplot object. However, given that there is sufficient space on a desktop device for a legend to be on the side, the approach currently used is to render a ggplotly interactive object for desktop users and a ggplot object for mobile users.

Iframing

Iframing apps can provide a great experience for users.

Template apps are build to be compatible with one of two approaches to iframing: