16  Classic Charts with highcharter

Let’s start by uploading the libraries we will use : tidyverse for the ETL, and highcharter and RColorBrewer for the charts.

# ETL
library(tidyverse)

# Charts
library(highcharter)
library(RColorBrewer)

17 Introduction

This section is dedicated to the library highcharter.

Within this package, the functions highchart() and hchart() are both used to create charts, but they serve different purposes and have distinct use cases. Let’s present both of them.

The highchart() function :

  • it’s a general function that initializes an empty Highcharts object.

  • This function is useful when you want to have fine-grained control over the chart’s configuration and need to build the chart step-by-step by adding series, axes, titles, and other components.

The hchart() function :

  • it’s a higher-level function that provides a simpler and quicker way to create a chart from a given data structure.

  • It is designed to be more user-friendly and automatically handles many of the chart configuration details based on the input data. This function is particularly useful when you want to create a chart quickly with minimal configuration.

Key Differences Level of Control:

  • highchart() : provides a blank chart and allows detailed customization by adding components step-by-step.

  • hchart() : provides a quick way to create a chart with sensible defaults based on the input data.

Ease of Use:

  • highchart() : requires more lines of code and a deeper understanding of Highcharts configuration options.

  • hchart() : requires fewer lines of code and is easier to use for creating standard charts.

Flexibility:

  • highchart() : offers more flexibility and is suitable for complex and highly customized charts.

  • hchart() : offers less flexibility but is ideal for quickly generating common types of charts.

In summary, use highchart() when you need full control over the chart’s configuration, and use hchart() when you want to quickly create a chart with minimal effort.

Now, we’re ready to start discovering and using both functions!

18 Create demo data frames

Now, let’s create 2 demo data frames that we will use to practice.

18.1 1 product

It’s a data frame with 6 variables :

  • 5 dimensions :

    • a calendar period.

      • and 3 related variables : calendar year, calendar month and a calendar month abbreviation.
    • a product description.

  • 1 measure : sales quantity.

# create Sales Qty
sales_qty <- c(1370,1528,1101,738,1229,1451,879,1505,1375,1146,1325,1156,1081,1258,894,700,1289,1207,926,1476,1254,1111,1175,881,916,1225,682,739,1056,1117,727,1233,839,862,862,702,740,934,603,468,903,901)

# create period of time
calendar_period <- c("10/1/2016","11/1/2016","12/1/2016","1/1/2017","2/1/2017","3/1/2017","4/1/2017","5/1/2017","6/1/2017","7/1/2017","8/1/2017","9/1/2017","10/1/2017","11/1/2017","12/1/2017","1/1/2018","2/1/2018","3/1/2018","4/1/2018","5/1/2018","6/1/2018","7/1/2018","8/1/2018","9/1/2018","10/1/2018","11/1/2018","12/1/2018","1/1/2019","2/1/2019","3/1/2019","4/1/2019","5/1/2019","6/1/2019","7/1/2019","8/1/2019","9/1/2019","10/1/2019","11/1/2019","12/1/2019","1/1/2020","2/1/2020","3/1/2020")

# combine into a data frame
df1 <- data.frame(calendar_period, sales_qty)

# add Product Description
df1$product_description <- "Product A"

# Format calendar_period as a date
df1$calendar_period <- as.Date(df1$calendar_period, format = '%m/%d/%Y')

# Get additional Calendar Fields: Month and Year

# add the Calendar Year
df1$calendar_year <- year(df1$calendar_period)

# add the Calendar.Month
df1$calendar_month <- month(df1$calendar_period)

# transform the Month number into a month abbreviation
# note that month.abb comes with [ and not (
df1$calendar_month_abb <- month.abb[df1$calendar_month]

# create factor 
df1$calendar_month_abb <- factor(df1$calendar_month_abb,
                              levels= c("Jan","Feb","Mar","Apr","May","Jun",
                                        "Jul","Aug","Sep", "Oct", "Nov", "Dec"))

# Get Results
sales_data <- df1


glimpse(df1)
Rows: 42
Columns: 6
$ calendar_period     <date> 2016-10-01, 2016-11-01, 2016-12-01, 2017-01-01, 2…
$ sales_qty           <dbl> 1370, 1528, 1101, 738, 1229, 1451, 879, 1505, 1375…
$ product_description <chr> "Product A", "Product A", "Product A", "Product A"…
$ calendar_year       <dbl> 2016, 2016, 2016, 2017, 2017, 2017, 2017, 2017, 20…
$ calendar_month      <dbl> 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,…
$ calendar_month_abb  <fct> Oct, Nov, Dec, Jan, Feb, Mar, Apr, May, Jun, Jul, …

18.2 2 products

The structure is similar to the previous one, but with 2 products (Product A and B).

#-----------------------------------
# create data frame for Product A
#-----------------------------------


# get Sales Qty
sales_qty <- c(1370,1528,1101,738,1229,1451,879,1505,1375,1146,1325,1156,1081,1258,894,700,1289,1207,926,1476,1254,1111,1175,881,916,1225,682,739,1056,1117,727,1233,839,862,862,702,740,934,603,468,903,901)

# get Period
calendar_period <- c("10/1/2016","11/1/2016","12/1/2016","1/1/2017","2/1/2017","3/1/2017","4/1/2017","5/1/2017","6/1/2017","7/1/2017","8/1/2017","9/1/2017","10/1/2017","11/1/2017","12/1/2017","1/1/2018","2/1/2018","3/1/2018","4/1/2018","5/1/2018","6/1/2018","7/1/2018","8/1/2018","9/1/2018","10/1/2018","11/1/2018","12/1/2018","1/1/2019","2/1/2019","3/1/2019","4/1/2019","5/1/2019","6/1/2019","7/1/2019","8/1/2019","9/1/2019","10/1/2019","11/1/2019","12/1/2019","1/1/2020","2/1/2020","3/1/2020")

# combine into a dataframe
df1<- data.frame(calendar_period, sales_qty)

# add Product Description
df1$product_description <- "Product A"



#-----------------------------------
# create data frame for Product B
#-----------------------------------

# get Sales Qty
sales_qty <- c(1623,1522,2306,1416,2214,2538,1841,1982,2749,1929,626,1280,1215,2693,1564,1836,1949,1923,1810,2181,2296,1671,1049,1229,1880,2041,1935,1617,1821,1940,1905,1699,2255,1853,522,1682,2261,1523,3210,1764,2230,1605)

# combine into a dataframe
df2<- data.frame(calendar_period, sales_qty)

# add Product Description
df2$product_description <- "Product B"

# stack data
df1 <- rbind(df1,df2)



#-----------------------------------
# work on dates
#-----------------------------------

# Format calendar_period as a date
df1$calendar_period <- as.Date(df1$calendar_period, format = '%m/%d/%Y')

# Get additional Calendar Fields: Month and Year

# add the Calendar Year
df1$calendar_year <- year(df1$calendar_period)

# add the Calendar.Month
df1$calendar_month <- month(df1$calendar_period)

# transform the Month number into a month abbreviation
# note that month.abb comes with [ and not (
df1$calendar_month_abb <- month.abb[df1$calendar_month]

# create factor 
df1$calendar_month_abb <- factor(df1$calendar_month_abb,
                              levels= c("Jan","Feb","Mar","Apr","May","Jun",
                                        "Jul","Aug","Sep", "Oct", "Nov", "Dec"))

# Get Results
sales_data2 <- df1


glimpse(df1)
Rows: 84
Columns: 6
$ calendar_period     <date> 2016-10-01, 2016-11-01, 2016-12-01, 2017-01-01, 2…
$ sales_qty           <dbl> 1370, 1528, 1101, 738, 1229, 1451, 879, 1505, 1375…
$ product_description <chr> "Product A", "Product A", "Product A", "Product A"…
$ calendar_year       <dbl> 2016, 2016, 2016, 2017, 2017, 2017, 2017, 2017, 20…
$ calendar_month      <dbl> 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,…
$ calendar_month_abb  <fct> Oct, Nov, Dec, Jan, Feb, Mar, Apr, May, Jun, Jul, …

19 Classic Charts

19.1 Basic line chart

Let’s use the demo data frame sales_data and create a simple line chart. We need 2 variables :

  • 1 dimension : a calendar period.

  • 1 measure : a sales quantity.

We display the measure using the function hc_add_series(), giving it a name, a color, and linking it to the variable sales_qty.

# set working dataframe
df1 <- sales_data


# chart
highchart() |>
  
  hc_title(text = "Sales Volumes") |>
  hc_subtitle(text = "in units") |> 
  hc_add_theme(hc_theme_google()) |>
  
  hc_xAxis(categories = df1$calendar_period) |>
  
  hc_add_series(name = "Sales", 
                color = "steelblue", 
                data = df1$sales_qty)

Now, you can change the theme and the color of the line. For example replace :

  • the theme with : hc_theme_538().

  • the color with : gold.

# set working dataframe
df1 <- sales_data


# chart
highchart() |>
  
  hc_title(text = "Sales Volumes") |>
  hc_subtitle(text = "in units") |> 
  hc_add_theme(hc_theme_538()) |>
  
  hc_xAxis(categories = df1$calendar_period) |>
  
  hc_add_series(name = "Sales", 
                color = "gold", 
                data = df1$sales_qty)

If we want to name the y axis, we can add a line of code : hc_yAxis(title = list(text = "Sales (units)")) .

Note : displaying the title of the y axis is often optional, as the info is already captured inside the chart’s title.

# set working dataframe
df1 <- sales_data


# chart
highchart() |>
  
  hc_title(text = "Sales Volumes") |>
  hc_subtitle(text = "in units") |> 
  hc_add_theme(hc_theme_google()) |>
  
  hc_xAxis(categories = df1$calendar_period) |>
  
  hc_yAxis(title = list(text = "Sales (units)")) |> # we can add this line

  hc_add_series(name = "Sales", 
                color = "steelblue", 
                data = df1$sales_qty)

If we want to display the values, we can add one more line of code inside the hc_add_series() :

# set working dataframe
df1 <- sales_data


# chart
highchart() |>
  
  hc_title(text = "Sales Volumes") |>
  hc_subtitle(text = "in units") |> 
  hc_add_theme(hc_theme_google()) |>
  
  hc_xAxis(categories = df1$calendar_period) |>

  hc_add_series(name = "Sales", 
                color = "steelblue", 
                dataLabels = list(align = "center", enabled = TRUE), # we can add this line
                data = df1$sales_qty)

19.2 MTM line chart

Now, let’s create a Month To Month (MTM) line chart.

This is very useful to :

  • compare the monthly evolution between 2 (or more) years.

  • identify easily any seasonality pattern.

First, let’s prepare the data. We want to have a data frame with :

  • 1 dimension : the calendar month.

  • 3 measures : the calendar years 2018, 2019 and 2020.

    • and the monthly sales of each calendar year.
# set working dataframe
df1 <- sales_data

# keep only the needed columns
df1 <- df1 |> select(calendar_month_abb, calendar_year, sales_qty)
    
# spread data
df1 <- df1 |> spread(calendar_year, sales_qty)

# replace zero by NA
df1[df1 == 0] <- NA

# display
df1
   calendar_month_abb 2016 2017 2018 2019 2020
1                 Jan   NA  738  700  739  468
2                 Feb   NA 1229 1289 1056  903
3                 Mar   NA 1451 1207 1117  901
4                 Apr   NA  879  926  727   NA
5                 May   NA 1505 1476 1233   NA
6                 Jun   NA 1375 1254  839   NA
7                 Jul   NA 1146 1111  862   NA
8                 Aug   NA 1325 1175  862   NA
9                 Sep   NA 1156  881  702   NA
10                Oct 1370 1081  916  740   NA
11                Nov 1528 1258 1225  934   NA
12                Dec 1101  894  682  603   NA

Now, let’s create our chart.

We’re going to display 3 calendar years : 2018, 2019 and 2020, and then will create 3 different series, with 3 different colors, using the function hc_add_series() .

highchart() |>
  
  hc_title(text = "MTM Actual Sales") |>
  hc_subtitle(text = "in units") |> 
  hc_xAxis(categories = df1$calendar_month_abb) |>
  hc_add_theme(hc_theme_google()) |>
  
  hc_add_series(name = "2018", 
                color = "mediumseagreen", 
                data = df1$`2018`) |> 
  
  hc_add_series(name = "2019", 
                color = "skyblue", 
                data = df1$`2019`) |>
  
  hc_add_series(name = "2020", 
                color = "gold", 
                data = df1$`2020`)

19.3 Column & bar chart

19.3.1 column

In this example, we’re going to display some YTD sales. We will look at the first quarter, so the YTD March.

Let’s notice the work flow below :

  • 1) Get Data.

  • 2) Filter.

  • 3) Transform.

  • 4) Chart.

It’s the work flow illustrated during the introduction of this chapter.

Besides, before performing the aggregation, we make sure that there are no missing sales values, replacing any missing values (NA) by zero.

We use the syntax : df1$sales_qty <- df1$sales_qty |> replace_na(0) .

By doing this, we ensure to have a correct aggregation (a sum in this case).

This type of chart is called “column”, and we define it by adding at the end the syntax : hc_chart(type = "column").

The chart shows some vertical columns.

#------------------
# Get data
#------------------

# set working dataframe
df1 <- sales_data



#------------------
# Filters
#------------------

# Select months
df1 <- df1 |> filter(calendar_month <= 3)


#------------------
# Transform
#------------------

# replace missing values by zero, if any
df1$sales_qty <- df1$sales_qty |> replace_na(0)

# aggregate
df1 <- df1 |> group_by(calendar_year) |>
      summarise(sales_qty = sum(sales_qty)
                )
        
#------------------
# Chart
#------------------


highchart() |> 
  hc_title(text = "YTD Sales Volumes") |>
  hc_subtitle(text = "in units") |> 
  hc_add_theme(hc_theme_google()) |>
  
  hc_xAxis(categories = df1$calendar_year) |> 
  
  hc_add_series(name = "Sales", 
                color = "mediumseagreen",
                dataLabels = list(align = "center", enabled = TRUE),
                data = df1$sales_qty) |>
  
  hc_chart(type = "column") 

19.3.2 bar

If at the end of the code, we change the chart type “column” by “bar”, we obtain the following chart, which is with horizontal bars.

#------------------
# Get data
#------------------

# set working dataframe
df1 <- sales_data



#------------------
# Filters
#------------------

# Select months
df1 <- df1 |> filter(calendar_month <= 3)


#------------------
# Transform
#------------------

# replace missing values by zero, if any
df1$sales_qty <- df1$sales_qty |> replace_na(0)

# aggregate
df1 <- df1 |> group_by(calendar_year) |>
      summarise(sales_qty = sum(sales_qty)
                )
        
#------------------
# Chart
#------------------


highchart() |> 
  hc_title(text = "YTD Sales Volumes") |>
  hc_subtitle(text = "in units") |> 
  hc_add_theme(hc_theme_google()) |>
  
  hc_xAxis(categories = df1$calendar_year) |> 
  
  hc_add_series(name = "Sales", 
                color = "mediumseagreen",
                dataLabels = list(align = "center", enabled = TRUE),
                data = df1$sales_qty) |>
  
  hc_chart(type = "bar") 

19.4 Columns & Multiple Products

19.4.1 stacking

In this example, we will use the library RColorBrewer. We define a value called “cols”, which contains the HEX codes of 7 colors of the palette “Set2”.

Regarding the chart :

  • the syntax changes a bit and we now use the hchart() function.

  • we also use a notion of “group”, where we affect the variable “product_description”.

    • Doing so, the series related to each product will be generated automatically, and with a color from the palette “Set2”.

Note :

  • We choose the option stacking = “normal” in the function hc_plotOptions()

  • This means that the series (here 2 series) are stacked

#------------------
# Get data
#------------------

# set working dataframe
df1 <- sales_data2



#------------------
# Filters
#------------------

# Select months
df1 <- df1 |> filter(calendar_month <= 3)


#------------------
# Transform
#------------------

# replace missing values by zero, if any
df1$sales_qty <- df1$sales_qty |> replace_na(0)

# aggregate
df1 <- df1 |> group_by(product_description, calendar_year) |>
      summarise(sales_qty = sum(sales_qty)
                )
        
#------------------
# Chart
#------------------

cols <- brewer.pal(7, "Set2")


hchart(df1, "column", 
       hcaes(x = calendar_year, 
             y = sales_qty,
             group = product_description), # we introduce the notion of group
       dataLabels = list(align = "center", enabled = TRUE)
       ) |>
      
      
      hc_plotOptions(series = list(stacking = "normal")) |>
  
  hc_title(text = "YTD Sales by Products") |>
  hc_subtitle(text = "in units") |>
  hc_colors(cols)

19.4.2 without settings

Let’s now create the same chart but :

  • without the RColorBrewer library.

  • without stacking the series.

    • removing the part :hc_plotOptions(series = list(stacking = "normal")) .

The chart is generated, with some by default colors.

#------------------
# Get data
#------------------

# set working dataframe
df1 <- sales_data2



#------------------
# Filters
#------------------

# Select months
df1 <- df1 |> filter(calendar_month <= 3)


#------------------
# Transform
#------------------

# replace missing values by zero, if any
df1$sales_qty <- df1$sales_qty |> replace_na(0)

# aggregate
df1 <- df1 |> group_by(product_description, calendar_year) |>
      summarise(sales_qty = sum(sales_qty)
                )
        

#------------------
# Chart
#------------------


hchart(df1, "column", 
       hcaes(x = calendar_year, 
             y = sales_qty,
             group = product_description), # we introduce the notion of group
       dataLabels = list(align = "center", enabled = TRUE)
       ) |>
      
      
      #hc_plotOptions(series = list(stacking = "normal")) |>
  
  hc_title(text = "YTD Sales by Products") |>
  hc_subtitle(text = "in units") 

19.4.3 self settings

We can define our own color for each serie, as below.

This time we will stack the series, and use the syntax : hc_plotOptions(series = list(stacking = "normal")) .

#------------------
# Get data
#------------------

# set working dataframe
df1 <- sales_data2



#------------------
# Filters
#------------------

# Select months
df1 <- df1 |> filter(calendar_month <= 3)


#------------------
# Transform
#------------------

# replace missing values by zero, if any
df1$sales_qty <- df1$sales_qty |> replace_na(0)

# aggregate
df1 <- df1 |> group_by(product_description, calendar_year) |>
      summarise(sales_qty = sum(sales_qty)
                )
        
# spread
df1 <- df1 |> spread(product_description, sales_qty)


#------------------
# Chart
#------------------

highchart() |> 
  
  hc_title(text = "YTD Sales by Products") |>
  hc_subtitle(text = "in units") |> 
  hc_add_theme(hc_theme_google()) |>
  
  hc_xAxis(categories = df1$calendar_year) |> 
  
  
  hc_add_series(name = "Product A", 
                color = "steelblue",
                dataLabels = list(align = "center", enabled = TRUE),
                data = df1$`Product A`) |> 
  
  hc_add_series(name = "Product B", 
                color = "gold",
                dataLabels = list(align = "center", enabled = TRUE),
                data = df1$`Product B`) |> 
  
  hc_chart(type = "column") |> 

  hc_plotOptions(series = list(stacking = "normal"))

19.5 Area chart

This is a chart a bit less popular than the previous ones, but still useful sometimes. Here is the syntax to generate it. We mention “area” within the function hchart() .

# set working dataframe
df1 <- sales_data2


# aggregate  
df1 <- df1 |> group_by(product_description, calendar_period) |>
      summarise(sales_qty = sum(sales_qty)
                )
        

# chart
cols <- brewer.pal(7, "Set2")
   

hchart(df1, 
       "area",
       hcaes(x = calendar_period, 
             y = sales_qty, 
             group = product_description)
       ) |>
      
      
      hc_plotOptions(series = list(stacking = "normal")) |>
      
      hc_title(text = "Sales by Products") |>
      hc_subtitle(text = "in units") |>
      hc_colors(cols)

19.6 Pie chart

Pie charts are getting less common nowadays, however, they are still a classic and simple way to visualize proportions.

Here is the syntax to generate it. We mention “pie” within the function hchart() .

# create a demo data frame
cities <- c("Taipei", "Kuala Lumpur", "Singapore")
pop <- c(2.6, 1.8, 5.6)

population_data <- data.frame(cities, pop)

# and now let’s create the pie
hchart(population_data, 
       "pie", 
       hcaes(name = cities, 
             y = pop)) |>  
  
  hc_title(text = "Population pie chart") |>
  
  hc_colors(c("#0198f9", "#800000", "#ffcc33"))

19.7 Tooltip customization

We can customize the charts, adding some tooltips, through the function hc_tooltip(), as described below.

When the mouse passes on top of the chart, a value is displayed.

  • it’s a good way to keep the chart light (without any value).

  • while displaying when needed the values with a customized info.

# let’s use the previous data frame
population_data <- population_data |> arrange(desc(pop))


# now let’s create a chart, with a tooltip
hchart(population_data,
       "column", 
       hcaes(x = cities, 
             y = pop), 
       color = "#0198f9", 
       name = "Population") |>

  hc_title(text = "Population by cities") |>
  hc_xAxis(title = list(text = "Cities")) |>
  hc_yAxis(title = list(text = "Population (millions)")) |>

  hc_tooltip(formatter = JS("function(){return this.y + ' M inhabitants';}"))

19.8 Box plot

A box plot is convenient representation to visualize the distribution of some values. Let’s take the example below :

  • we have 4 suppliers (A, B, C, D).

  • with different transit lead times, recorded through 10 observations.

We want to visualize those different transit lead times, and their distribution (and distance) versus a mean value.

First, let’s create a demo data frame :

# Create a demo data frame
set.seed(123)  # For reproducibility

df1 <- data.frame(
  
  supplier = rep(c("Supplier A", "Supplier B", "Supplier C", "Supplier D"), 
                 each = 10),
  
  lead_time = c(rnorm(10, mean = 37, sd = 1),  # Lead times for Supplier A
                rnorm(10, mean = 35, sd = 1.5), # Lead times for Supplier B
                rnorm(10, mean = 33, sd = 0.5), # Lead times for Supplier C
                rnorm(10, mean = 42, sd = 2))   # Lead times for Supplier D
)

glimpse(df1)
Rows: 40
Columns: 2
$ supplier  <chr> "Supplier A", "Supplier A", "Supplier A", "Supplier A", "Sup…
$ lead_time <dbl> 36.43952, 36.76982, 38.55871, 37.07051, 37.12929, 38.71506, …

Now let’s create a box plat chart, using the library highcharter and the function hcboxplot() :

hcboxplot(
      x = df1$lead_time,
      var = df1$supplier,
      name = "Transit time",
      color = "#2980b9"
    ) |>
      
      hc_chart(type = "column") |>
      
      hc_title(text = "Transit time Distribution per Supplier") |>
      hc_subtitle(text = "in days")

20 Additional Features

20.1 Display of percentages

How about displaying some percentages?

First, let’s create a simple data frame.

In this example we look at some projected inventories (of a portfolio of products) and the projected percentage (e.g. the ratio) of overstocks inventories. We want to display this projected ratio in the coming months.

# create vectors
period <- c("2026-01-01", "2026-02-01", "2026-03-01", "2026-04-01")

ratio <- c(68, 52, 47, 44)

# combine into a data frame
df1 <- data.frame(period, ratio)

# format as Date
df1$period <- as.Date(df1$period, format = "%Y-%m-%d")

# display
df1
      period ratio
1 2026-01-01    68
2 2026-02-01    52
3 2026-03-01    47
4 2026-04-01    44

Now we can create the chart, using the syntax {point.y:.1f}% as format for the dataLabels, and also for the hc_tooltip .

Notes :

  • we also display and format here the hc_yAxis .

    • using the syntax hc_yAxis(labels = list(format = "{value}%")) .
  • the ratio in the data frame is expressed as 68 and not 0.68 .The conversion in percentage is done in the highchart.

highchart() |>
  
  hc_title(text = "ratio of overstocks inventories") |>
      hc_subtitle(text = "as % of total projected inventories") |> 
      hc_add_theme(hc_theme_google()) |>
      
      hc_xAxis(categories = df1$period) |>
      
      hc_yAxis(labels = list(format = "{value}%")) |>
      
      hc_add_series(name = "share of Overstocks", 
                    color = "orange", 
                    data = df1$ratio,
                    dataLabels = list(enabled = TRUE, format = '{point.y:.1f}%')
      ) |>
      
      hc_tooltip(pointFormat = '{point.y:.1f}%')

20.2 Horizontal reference lines

Having some reference lines can make the reading of a chart faster and more insightful, for example :

  • how is the observed value vs a min & max thresholds or vs an average value ?

    • are we frequently below or above those thresholds ?

    • are we significantly below or above those thresholds ?

  • do we need to take any actions ?

To illustrate the syntax, we will use the simple demo data frame below, and display a monthly production charge vs a minimum and maximum production capacity.

#---------------------
# create demo data frame
#---------------------

# create vectors
period <- c("M", "M+1", "M+2", "M+3", "M+5")

charge <- c(700, 800, 1000, 300, 600)

max_capacity <- c(800, 800, 800, 800, 800)

min_capacity <- c(300, 300, 300, 300, 300)

# combine into a data frame
df1 <- data.frame(period,
                  charge,
                  max_capacity,
                  min_capacity)


#---------------------
# chart
#---------------------

# chart
highchart() |>
  
  hc_title(text = "Production Charge vs Capacity") |>
  hc_subtitle(text = "in units") |> 
  hc_add_theme(hc_theme_google()) |>
  
  hc_xAxis(categories = df1$period) |>
  
  hc_add_series(name = "Charge", 
                color = "gold", 
                dataLabels = list(align = "center", enabled = TRUE),
                type ='column',
                data = df1$charge) |>
  
  
  hc_add_series(name = "Min Capacity", 
                color = "mediumseagreen", 
                data = df1$min_capacity) |>
  
  hc_add_series(name = "Max Capacity", 
                color = "salmon", 
                data = df1$max_capacity)

20.3 Vertical reference lines

Reference lines can also be vertical.

They can be used to display specific periods of time for example.

Let’s use the previous data frame “sales_data” :

# set working dataframe
df1 <- sales_data


# Convert the dates to milliseconds since epoch for plotLines
plot_line_date_1 <- as.numeric(as.POSIXct("2018-07-01")) * 1000
plot_line_date_2 <- as.numeric(as.POSIXct("2019-06-01")) * 1000


# chart
highchart() |>
  
  hc_title(text = "Sales Volumes") |>
  hc_subtitle(text = "in units") |> 
  hc_add_theme(hc_theme_google()) |>
  
  
  hc_add_series(data = df1, 
                    type = "line", 
                    hcaes(x = calendar_period, y = sales_qty),
                    name = "Sales") %>%
  
  
  hc_xAxis(type = "datetime", # Ensure x-axis is treated as datetime
               plotLines = list(
                 list(
                   value = plot_line_date_1,
                   color = "mediumseagreen",
                   width = 2,
                   label = list(text = "Beginning of Horizon")
                 ),
                 
                 list(
                   value = plot_line_date_2,
                   color = "red",
                   width = 2,
                   label = list(text = "End of Horizon")
                 )

               ))

In this chart, we can for example :

  • highlight a specific horizon of time where something happened.

  • display a training horizon where we want to train our Statistical Forecasts model.

20.4 Background

To make the reading easier, we also can add a background to our chart.

In the example below, we will :

  • add a lightgray background.

  • label it as “Year-To-Date”, to mention the historical period of time until now.

#---------------------
# create demo data frame
#---------------------

# create vectors
calendar_month_abb <- c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")

sales_qty <- c(700, 800, 1000, 300, 600, 800, 900, 500, 400, 1200, 1000, 800)

# combine into a data frame
df1 <- data.frame(calendar_month_abb,
                  sales_qty)

# create a factor
df1$calendar_month_abb <- factor(df1$calendar_month_abb,
                                 levels = c("Jan","Feb","Mar","Apr","May","Jun",
                                            "Jul","Aug","Sep", "Oct", "Nov", "Dec"))




#---------------------
# chart
#---------------------


highchart() |>
  
  hc_add_series(name = "sales",
                color = "mediumseagreen", 
                type = 'column',
                dataLabels = list(align = "center", enabled = TRUE),
                data = df1$sales_qty) |>
  
  hc_title(text = "Monthly Demand") |>
  hc_subtitle(text = "in units") |> 
  
  
  hc_xAxis(categories = df1$calendar_month_abb,
           
           plotLines = list(
             list(label = list(text = "End of YTD Period"), 
                  color = "orange",
                  width = 3,
                  value = 5) 
               ),
           
           plotBands = list(
             list(from = 0, 
                  to = 5,
                  color = "lightgray",
                  label = list(text = "Year-To-Date")
                  )
             )
           
           ) |> # close hc_xAxis
  
  
  hc_add_theme(hc_theme_google()) 

There’s (much) more!

For more examples, let’s have a look at the website of the R package highcharter .