Some Highcharter Graphs

code
graphics
r
Author

Paul Smith

Published

January 12, 2025

Introduction

In my previous post about {highcharter}, I considered changing some of the defaults for a scatter graph to make it look more appealing and be more accessible. This post will focus on plotting the following different types of graphs:

  • Bar charts, including grouped bar charts
  • Icon plots
  • Line graphs
  • Stream graphs

First, we will load the packages we require in this post. The {highcharter} (Kunst 2022) and {tidyverse} (Wickham et al. 2019) packages are used throughout. The {medicaldata} package (Higgins 2021) is used to create the bar charts and (some of) the line graphs. The icon plots use data obtained via the {clmnis} package (Dempsey 2025).

Kunst, Joshua. 2022. Highcharter: A Wrapper for the ’Highcharts’ Library. https://CRAN.R-project.org/package=highcharter.
Wickham, Hadley, Mara Averick, Jennifer Bryan, Winston Chang, Lucy D’Agostino McGowan, Romain François, Garrett Grolemund, et al. 2019. “Welcome to the tidyverse.” Journal of Open Source Software 4 (43): 1686. https://doi.org/10.21105/joss.01686.
Higgins, Peter. 2021. Medicaldata: Data Package for Medical Datasets. https://CRAN.R-project.org/package=medicaldata.
Code
library(highcharter)
library(paletteer) # colour palettes
library(tidyverse)
library(gapminder)

# medical data package
# use 'remotes::install_github("higgi13425/medicaldata")' to access the 'thiomon' dataset
library(medicaldata)

# obtaining MP information
# remotes::install_github("houseofcommonslibrary/clmnis")
library(clmnis)

library(fontawesome)

Bar charts

For the bar charts, I’m using data obtained from the {medicaldata} package. Loading the Covid data1, and ensuring factors are coded correctly.

1 Description of the dataset can be found here

Code
covid <- tibble(medicaldata::covid_testing)

covid <- covid |>
  mutate(across(c(gender, test_id, demo_group, drive_thru_ind, result, payor_group, patient_class), as_factor))

# look at levels of the factors
#sapply(covid[, c("gender", "test_id", "demo_group", "drive_thru_ind", "result", "payor_group", "patient_class")], levels)

covid

Let’s start with a simple bar chart, showing the frequency of negative and positive Covid results.

First we create counts of positive, negative and invalid results.

Code
result_counts <- covid |>
  count(result) |>
  # capitalise first letter
  mutate(result = str_to_title(as.character(result))) |>
  arrange(desc(n))
Code
# Create the bar chart
hchart(
    result_counts,
    type = "bar",
    hcaes(x = result, y = n),
    name = "Results"
  ) |>
  hc_title(text = "Results of Covid Tests") |>
  hc_xAxis(title = list(text = "Result")) |>
  hc_yAxis(title = list(text = "Count")) |>
  hc_colors("#003087") |>
  # a source
  hc_credits(
    text = "Data obtained from the {medicaldata} package",
    href = "https://higgi13425.github.io/medicaldata/",
    enabled = TRUE
    ) |>
  hc_exporting(
    accessibility = list(
      enabled = TRUE # default value is TRUE
      ),
    enabled = TRUE,
    filename = "covid_bar"
  ) |>
  hc_plotOptions(
    accessibility = list(
      enabled = TRUE,
      keyboardNavigation = list(enabled = TRUE)
      )
    )

Grouped bar chart

Group results by gender.

Code
result_counts_gender <- covid |>
  group_by(gender) |>
  count(result) |>
  # capitalise first letter
  mutate(result = str_to_title(as.character(result)))
The hover box issues

The hard part here seems to be getting the hover box to output the correct things. Specifically, I don’t know how to get the names of the y-axis titles (“Positive”, etc.), without doing nested if statements. It must involve the formatter but I’m not sure how.

FIXED: use this.key to get the names.

Code
hchart(
  result_counts_gender,
  type = "bar",
  hcaes(x = result, y = n, group = gender) 
  ) |>
  hc_colors(c("#003087", "#006747")) |>
  hc_title(text = "Lots of people don't have Covid",
           align = "left") |>
  hc_subtitle(text = "A bar chart showing Covid test results, split by gender.",
              align = "left") |>
  hc_xAxis(title = list(text = "Result")) |>
  hc_yAxis(title = list(text = "Count")) |>
  # a source
  hc_credits(
    text = "Data obtained from the {medicaldata} package",
    href = "https://higgi13425.github.io/medicaldata/",
    enabled = TRUE
    ) |>
   hc_tooltip(
      formatter = JS("function () {
       if (this.series.name == 'male') {
        return `<b>Male</b></br>${this.y} ${this.key} results`
      } else if (this.series.name == 'female') {
        return `<b>Female</b></br> ${this.y} ${this.key} results`
      }}")
   ) |>
  hc_exporting(
    accessibility = list(
      enabled = TRUE # default value is TRUE
      ),
    enabled = TRUE,
    filename = "covid_bar"
  ) |>
  hc_plotOptions(
    accessibility = list(
      enabled = TRUE,
      keyboardNavigation = list(enabled = TRUE)
      )
    )

Icons plot

Let’s look at the gender split in parliament as of 31st December 2024. We can extract the data using {clmnis} (Dempsey 2025), which is an R package for downloading data from the UK Parliament’s Members Names Information Service (MNIS).

Dempsey, Noel. 2025. Clmnis: An r Package for Downloading Data from the Parliamentary Members Names Information Service. https://github.com/houseofcommonslibrary/clmnis.

Obtaining the data:

Code
mps <- clmnis::fetch_mps(on_date = "2024-12-31")

mps
Code
mps_gender <- mps |>
  count(gender) |>
  mutate(
    gender = case_match(
      gender,
      "M" ~ "Male MPs",
      "F" ~ "Female MPs"
    )
  ) |>
  add_column(col = c("#4477AA", "#EE6677"))
        
mps_gender

A basic icon chart

Plotting a simple icon chart. Choose between the “parliament view” and the “circular view” by selecting the relevant tab below.

Code
hchart(
  mps_gender,
  "item",
  hcaes(
    name = gender,
    y = n,
    color = col
  ),
  name = "Number of MPs",
  showInLegend = TRUE,
  size = "100%",
  center = list("50%", "75%"),
  startAngle = -100,
  endAngle  = 100
) %>%
  hc_title(
    text = "Male MPs make up a significant majority of the House of Commons",
    align = "left"
    ) %>%
  hc_subtitle(
    text = "An item chart showing the proportion of male and femal MPs in the House of Commons, on 31st December 2024.",
    align = "left"
    ) |>
  hc_legend(labelFormat = '{name} <span style="opacity: 0.4">{y}</span>') |>
  hc_exporting(
    accessibility = list(
      enabled = TRUE # default value is TRUE
      ),
    enabled = TRUE,
    filename = "mp_icon_plot"
  ) |>
  hc_plotOptions(
    accessibility = list(
      enabled = TRUE,
      keyboardNavigation = list(enabled = TRUE)
      )
    )

To change the plot to a circular layout, set startAngle = -180 and endAngle = 180 and change the center argument.

Code
hchart(
  mps_gender,
  "item",
  hcaes(
    name = gender,
    y = n,
    color = col
  ),
  name = "Number of MPs",
  showInLegend = TRUE,
  size = "100%",
  center = list("50%", "50%"),
  startAngle = -180,
  endAngle  = 180
) %>%
  hc_title(
    text = "Male MPs make up a significant majority of the House of Commons",
    align = "left"
    ) %>%
  hc_subtitle(
    text = "An item chart showing the proportion of male and femal MPs in the House of Commons, on 31st December 2024.",
    align = "left"
    ) |>
  hc_legend(labelFormat = '{name} <span style="opacity: 0.4">{y}</span>') |>
  hc_exporting(
    accessibility = list(
      enabled = TRUE # default value is TRUE
      ),
    enabled = TRUE,
    filename = "mp_icon_plot"
  ) |>
  hc_plotOptions(
    accessibility = list(
      enabled = TRUE,
      keyboardNavigation = list(enabled = TRUE)
      )
    )

Adding symbols to the icon chart

What if we want female and male symbols instead of circles, and the icons arranges in a rectangle?

First, lets add the icons to the tibble. We will use the {fontawesome} package (Iannone 2024), alongside the function given in the {highcharter} vignette to obtain the symbols.

Iannone, Richard. 2024. Fontawesome: Easily Work with ’Font Awesome’ Icons. https://github.com/rstudio/fontawesome.
Code
fa_to_png_to_datauri <- function(name, ...) {
  tmpfl <- tempfile(fileext = ".png")
  fontawesome::fa_png(name, file = tmpfl, ...)
  knitr::image_uri(tmpfl)

}

Adding the ‘person’ and ‘person-dress’ symbols to the tibble.

Code
mps_gender_icon <- mps_gender |>
  add_column(faico = c("person-dress", "person"))

mps_gender_icon <- mps_gender_icon |>
  mutate(
    uri = map2_chr(faico, col, ~fa_to_png_to_datauri(.x, fill = .y)),
    marker = map(uri, ~ list(symbol = str_glue("url({data_uri})", data_uri = .x)))
  )

Creating the new icon plot.

Code
hchart(
  mps_gender_icon,
  "item",
  hcaes(
    name = gender,
    y = n,
    color = col
  ),
  name = "Number of MPs",
  showInLegend = TRUE,
  size = "100%"
) |>
  hc_title(
    text = "Male MPs make up a significant majority of the House of Commons",
    align = "left"
    ) |>
  hc_subtitle(
    text = "An item chart showing the proportion of male and femal MPs in the House of Commons, on 31st December 2024.",
    align = "left"
    ) |>
  hc_legend(labelFormat = '{name} <span style="opacity: 0.4">{y}</span>') |>
  hc_plotOptions(
    item = list(
      layout = "vertical",
      rows = 18 # Specify the number of rows here
    )
  ) |>
  hc_exporting(
    accessibility = list(
      enabled = TRUE # default value is TRUE
      ),
    enabled = TRUE,
    filename = "mp_icon_plot"
  ) |>
  hc_plotOptions(
    accessibility = list(
      enabled = TRUE,
      keyboardNavigation = list(enabled = TRUE)
      )
    )

Line graphs

Using data obtained from the {gapminder} package (Bryan 2023), we will produce a line graph. A few new things here:

Bryan, Jennifer. 2023. Gapminder: Data from Gapminder. https://CRAN.R-project.org/package=gapminder.
  • We have used the {paletteer} package (Hvitfeldt 2021) to obtain a colour palette.
  • We have added labels to the lines directly, using plotOptions.series.label.
  • We have set the linewidth directed, in plotOptions.
  • We have removed markers from the lines except when hovered over, in plotOptions.
Hvitfeldt, Emil. 2021. Paletteer: Comprehensive Collection of Color Palettes. https://github.com/EmilHvitfeldt/paletteer.
Code
gapminder_line <- gapminder |>
  filter(country %in% c("United Kingdom","France","Germany","Italy","Netherlands"))

hchart(gapminder_line, 
       "line",
        hcaes(x = year, y = pop, group = country)) |>
  hc_title(
    text = "The Netherlands has a much smaller population than Germany.",
    align = "left"
    ) |>
  hc_subtitle(
    text = "A line chart showing changes in population between 1952 and 2007.",
    align = "left"
    ) |>
  hc_xAxis(title = list(text = "Year")) |>
  hc_yAxis(title = list(text = "Population")) |>
  # a source
  hc_credits(
    text = "Data obtained from the {gapminder} package",
    href = "https://www.gapminder.org/",
    enabled = TRUE
    ) |>
  hc_colors(colors = as.character(paletteer::paletteer_d("lisa::FridaKahlo"))) |>
  hc_exporting(
    accessibility = list(
      enabled = TRUE # default value is TRUE
      ),
    enabled = TRUE,
    filename = "population_line"
  ) |>
  hc_plotOptions(
    series = list(
   label = list(
        enabled = TRUE, # add labels to lines
        style = list(
          fontWeight = "bold",
          color = "#333"
        ),
        connectorAllowed = FALSE # include line connecting label to series?
      ),
      lineWidth = 2,
      marker = list(
        enabled = FALSE, # remove markers
        symbol = "circle",
        states = list(
          hover = list(
            enabled = TRUE # enable markers if hovered over
          )
        )
      )),
    accessibility = list(
      enabled = TRUE,
      keyboardNavigation = list(enabled = TRUE)
      )
    )

Stream graphs

Copying the line graph we produced above.

Code
hchart(gapminder_line, 
       "streamgraph", zoomType = "x",
        hcaes(x = year, y = pop, group = country)) |>
  hc_title(
    text = "The populations in these countries are relatively steady over time.",
    align = "left"
    ) |>
  hc_subtitle(
    text = "A line chart showing changes in population between 1952 and 2007.",
    align = "left"
    ) |>
  hc_xAxis(title = list(text = "Year")) |>
  hc_yAxis(visible = FALSE, 
           startOnTick = FALSE, endOnTick = FALSE, 
           title = list(text = "Population")) |>
  # a source
  hc_credits(
    text = "Data obtained from the {gapminder} package",
    href = "https://www.gapminder.org/",
    enabled = TRUE
    ) |>
  hc_colors(colors = as.character(paletteer::paletteer_d("lisa::FridaKahlo"))) |>
  hc_exporting(
    accessibility = list(
      enabled = TRUE # default value is TRUE
      ),
    enabled = TRUE,
    filename = "population_line"
  ) |>
  hc_plotOptions(
    series = list(
   label = list(
        enabled = TRUE, # add labels to lines
        style = list(
          fontWeight = "bold",
          color = "#555555"
        ),
        connectorAllowed = FALSE # include line connecting label to series?
      ),
      lineWidth = 2,
      marker = list(
        enabled = FALSE, # remove markers
        symbol = "circle",
        states = list(
          hover = list(
            enabled = FALSE # enable markers if hovered over
          )
        )
      )),
    accessibility = list(
      enabled = TRUE,
      keyboardNavigation = list(enabled = TRUE)
      )
    )

Copying the example given in the Highchart demos. First, we will create a list of data – medals won by countries in the Winter Olympics, which is taken from Olympedia.

Code
custom_colors <- as.character(paletteer_d(`"awtools::bpalette"`, n = 3))
  
# Categories
categories <- c(
  '',
  '1924 Chamonix', '1928 St. Moritz', '1932 Lake Placid', 
  '1936 Garmisch-Partenkirchen', '1940 <i>Cancelled (Sapporo)</i>', 
  '1944 <i>Cancelled (Cortina d\'Ampezzo)</i>', '1948 St. Moritz', 
  '1952 Oslo', '1956 Cortina d\'Ampezzo', '1960 Squaw Valley', 
  '1964 Innsbruck', '1968 Grenoble', '1972 Sapporo', 
  '1976 Innsbruck', '1980 Lake Placid', '1984 Sarajevo', 
  '1988 Calgary', '1992 Albertville', '1994 Lillehammer', 
  '1998 Nagano', '2002 Salt Lake City', '2006 Turin', 
  '2010 Vancouver', '2014 Sochi', '2018 PyeongChang', 
  '2022 Beijing'
)

# medal data
medal_data <- list(
  list(name = "Finland", 
       data = c(0, 11, 4, 3, 6, 0, 0, 6, 9, 7, 8, 10, 5, 5, 7, 9, 13, 7, 7, 6, 12, 7, 9, 5, 5, 6, 8)),
  list(name = "Austria", 
       data = c(0, 3, 4, 2, 4, 0, 0, 8, 8, 11, 6, 12, 11, 5, 6, 7, 1, 10, 21, 9, 17, 17, 23, 16, 17, 14, 18)),
  list(name = "Sweden", 
       data = c(0, 2, 5, 3, 7, 0, 0, 10, 4, 10, 7, 7, 8, 4, 2, 4, 8, 6, 4, 3, 3, 7, 14, 11, 15, 14, 18))
)

Now we will create the stream graph. A few novel things here:

  • I built the graph before adding the data. Note that the data is only added in the very last line, using `hc_add_series_list()
  • Annotations were added using hc_annotations().
Code
# Create the chart
highchart() |>
  hc_chart(type = "streamgraph", zoomType = "x", marginBottom = 30) |>
  hc_colors(colors = custom_colors) |>
  hc_title(text = "Winter Olympic Medal Wins", align = "left", floating = TRUE) |>
  hc_subtitle(
    text = 'Source: <a href="https://www.olympedia.org/statistics">olympedia.org</a>', 
    align = "left", y = 30, floating = TRUE
  ) |>
  hc_xAxis(
    categories = categories, 
    crosshair = TRUE,
    labels = list(
      align = "left", 
      rotation = 270, 
      reserveSpace = FALSE),
    lineWidth = 0, # remove x-axis line
    tickWidth = 0 # remove x-axis tick
  ) |>
  hc_yAxis(visible = FALSE, 
           startOnTick = FALSE, endOnTick = FALSE, 
           minPadding = 0.1, maxPadding = 0.15) |>
  hc_legend(enabled = FALSE) |>
  hc_annotations(
    list(
      labels = list(
        list(point = list(x = 5.5, xAxis = 0, y = 0, yAxis = 0), 
             text = "Cancelled<br>during<br>World War II"),
        list(point = list(x = 18, xAxis = 0, y = 15, yAxis = 0), 
             text = "Soviet Union fell,<br>Germany united"),
        list(point = list(x = 24.25, xAxis = 0, y = 20, yAxis = 0), 
             text = "Russia banned from<br>the Olympic Games<br> in 2017")
      )
    )
  ) |>
  hc_plotOptions(
    series = list(
      label = list(
        minFontSize = 5, 
        maxFontSize = 15, 
        style = list(color = "rgba(255,255,255,0.75)")),
      accessibility = list(exposeAsGroupOnly = TRUE)
    )
  ) |>
  hc_add_series_list(medal_data)

Other charts

I have shamelessly stolen this next chart from Joshua Kunst who created it in a {highcharter} article, and in turn stole the idea from the Wall Street Journal. But, it is such a nice chart that I can’t not reproduce it here.

Code
data(vaccines)

fntltp <- JS("function(){
  return this.point.x + ' ' +  this.series.yAxis.categories[this.point.y] + ': ' +
  Highcharts.numberFormat(this.point.value, 2);
}")

plotline <- list(
  color = "#fde725", value = 1963, width = 2, zIndex = 5,
  label = list(
    text = "Vaccine Intoduced", verticalAlign = "top",
    style = list(color = "#606060"), textAlign = "left",
    rotation = 0, y = -5
  )
)

hchart(
  vaccines, 
  "heatmap", 
  hcaes(
    x = year,
    y = state, 
    value = count
    )
  ) |>
  hc_colorAxis(
    stops = color_stops(10, viridisLite::inferno(10, direction = -1)),
    type = "logarithmic"
  ) |>
  hc_yAxis(
    title = list(text = ""),
    reversed = TRUE, 
    offset = -20,
    tickLength = 0,
    gridLineWidth = 0, 
    minorGridLineWidth = 0,
    labels = list(style = list(fontSize = "9px"))
  ) |>
  hc_tooltip(
    formatter = fntltp
    ) |>
  hc_xAxis(
    plotLines = list(plotline)) |>
  hc_title(
    text = "Infectious Diseases and Vaccines"
    ) |>
  hc_subtitle(
    text = "Number of cases per 100,000 people"
  ) |> 
  hc_legend(
    layout = "horizontal",
    verticalAlign = "top",
    align = "left",
    valueDecimals = 0
  ) |>
  hc_size(height = 900)  |>
  hc_exporting(
    accessibility = list(
      enabled = TRUE # default value is TRUE
      ),
    enabled = TRUE,
    filename = "vaccines"
  ) |>
  hc_plotOptions(
    accessibility = list(
      enabled = TRUE,
      keyboardNavigation = list(enabled = TRUE)
      )
    )

Citation

BibTeX citation:
@online{smith2025,
  author = {Smith, Paul},
  title = {Some {Highcharter} {Graphs}},
  date = {2025-01-12},
  url = {https://pws3141.github.io/blog/posts/03-highcharter_graphs/},
  langid = {en}
}
For attribution, please cite this work as:
Smith, Paul. 2025. “Some Highcharter Graphs.” January 12, 2025. https://pws3141.github.io/blog/posts/03-highcharter_graphs/.