Skip to contents

Line Charts and Time-Series

Adding Multiple Series

We’ll plot a line chart with the gapminder data. Note that we need to drop the levels when plotting individual countries. This is due to the fact that SveltePlots expects us to provide the number of colors equal to the number of levels in the column for the color mapping. So we can either drop the extra levels or coerce the column into a character vector.

In the chart below, we added 3 additional series for the the countries Chile and Germany. We specify group = country for the legend to display the country name.

data("gapminder")

gapminder <- gapminder |> 
  dplyr::mutate(
    country = as.character(country),
    year = lubridate::ymd(paste0(year, "-01-01"))
  )

sp <- SveltePlots::sp(
  data = gapminder |> 
    dplyr::group_by(year, continent) |> 
    dplyr::summarise(
      lifeExp = mean(lifeExp)
    ) |> 
    dplyr::ungroup(),
  mapping = spaes(x = year, y = lifeExp, group = continent),
  type = "line",
  combine_same_groups = FALSE
) |> 
  sp_add_series(
    data = gapminder |> 
      dplyr::filter(country == "Germany"),
    mapping = spaes(x = year, y = lifeExp, group = country),
    type = "line", 
    colors = "gold"
  ) |> 
  sp_add_series(
    gapminder |> 
      dplyr::filter(country == "Chile"),
    mapping = spaes(x = year, y = lifeExp, group = country), 
    type = "line", 
    colors = "silver"
  ) |> 
  sp_add_series(
    gapminder |> 
      dplyr::filter(country == "Chile"),
    mapping = spaes(x = year, y = lifeExp, group = country),
    type = "points", 
    size = 3, 
    tooltip = FALSE
  ) 

We can add a title with sp_title()

sp |> 
 sp_title(
   title = "Life Expectancy Over Time",
   font_size = 26
 ) 

For the above graph we added a points series and a line series for Chile and both series show up in the legend because of combine_same_groups = FALSE in the sp function. We do not show the tooltip for the points series for Chile.

Legends and Hovering

By clicking the legend, we can add and remove series. Sometimes, it is nice to control multiple series that correspond to the same groups with one click. By default, SveltePlots uses only one legend to control all series for the same group. Different from the gapminder chart above where we had combine_same_groups = FALSE, in this chart we have combine_same_groups = TRUE, which is the default. This combines different line and points series into one legend entry.

sp(
  data = purchases, 
  type = "line",
  mapping = spaes(x = date, y = revenue_roll, group = age),
  colors = c("red", "green", "blue"),
  combine_same_groups = TRUE
) |>
  sp_add_series(
    data = purchases,
    mapping = spaes(x = date, y = revenue, group = age),
    type = "points", 
    alpha = 0.4
  ) |> 
  sp_add_series(
    data = purchases[purchases$revenue == max(purchases$revenue), ], 
    mapping = spaes(x = date, y = revenue, group = age),
    type = "points",
    size = 5, 
    tooltip = F
  ) 

The line and points, which are two different series, are controlled by one legend entry.

Similarly, we can also control each series we are plotting with the legend by specifying combine_same_groups = FALSE. Then we can add and remove each series individually.

sp <- sp(
  data = purchases, 
  mapping = spaes(x = date, y = revenue_roll, group = age),
  type = "line",
  colors = c("red", "green", "blue"),
  combine_same_groups = FALSE
) |>
  sp_add_series(
    data = purchases, 
    mapping = spaes(x = date, y = revenue, group = age),
    type = "points",
    alpha = 0.4,
    tooltip = F, 
  ) |> 
  sp_add_series(
    data = purchases[purchases$revenue == max(purchases$revenue), ], 
    mapping = spaes(x = date, y = revenue, group = age),
    type = "points", 
    size = 5,
    tooltip = F, 
    include_legend = F
  ) 

sp

We also removed the legend with include_legend = F for the last series.

Below is another example with the mtcars data set where we would like to highlight points which have greater or equal to 28 miles per gallon. In this case we should choose combine_same_groups = FALSE to have control over both series with the two legend entries.

data("mtcars")
sp <- sp(
  mtcars |> dplyr::filter(mpg < 28), 
  mapping = spaes(x = mpg, y = wt),
  type = "points", 
  colors = "black",
  combine_same_groups = FALSE
) |>
  sp_add_series(
    data = mtcars |>
      dplyr::filter(mpg >= 28),
    mapping = spaes(x = mpg, y = wt), 
    type = "points", 
    size = 5,
    colors = "red"
  ) 

sp

Line Breaks

We can combine lines when we are not having any NA values in the data set.

set.seed(123)
purchases_line_breaks <- purchases[sample(1:nrow(purchases), size = nrow(purchases)*0.7), ]

sp <- sp(
  data = purchases_line_breaks,
  mapping = spaes(x = date, y = revenue_roll, group = age),
  type = "line",
  colors = c("red", "green", "blue")
) |> 
  sp_add_series(
    data = purchases_line_breaks, 
    mapping = spaes(x = date, y = revenue_roll, group = age),
    type = "points", 
    tooltip = F
  ) 
sp

Similarly, we can break lines when having NA values in the data set for the y-values. Notice, when there are no two consecutive dates, there will not be a line and therefore, we added a points series as well.

purchases_line_breaks <- purchases
purchases_line_breaks$revenue_roll[sample(1:nrow(purchases), size = nrow(purchases)*0.2)] <- NA

sp <- sp(
  data = purchases_line_breaks,
  mapping = spaes(x = date, y = revenue_roll, group = age),
  type = "line",
  colors = c("red", "green", "blue")
) |>   
  sp_add_series(
    data = purchases_line_breaks, 
    mapping = spaes(x = date, y = revenue_roll, group = age),
    type = "points",
    tooltip = F
  ) 

sp

Confidence Intervals

We can specify confidence intervals or bands with the y_min and y_max arguments in the spaes function.

data("confidence_intervals")

sp(
  data = confidence_intervals, 
  mapping = spaes(x = .index, y = .value, group = .key),
  type = "line",
  size = 2
) |> 
  sp_add_series(
    data = confidence_intervals |> 
      dplyr::mutate(.key = as.character(.key)) |>
      na.omit(),
    mapping = spaes(x = .index, y_min = .conf_lo, y_max = .conf_hi, group = .key),
    type = "bands"
  ) 

Facetting

When we want to create multiple charts based on a column or multiple columns in the data, we need to specify the faceting variable in the sp() function with the facet_var argument. It takes the name of a column as a character or a character vector of multiple columns which present in the data set. In the sp_facet() function, we can specify how many rows and column we want. By default, the scales are fixed and can be change to be free as well. The sp_facet function should always be the last funtion used in the chain.

data("penguins")
sp <- sp(
  data = penguins,
  mapping = spaes(x = flipper_length_mm, y = bill_length_mm, group = species),
  type = "points",
  facet_var = "sex"
) |> 
  SveltePlots::sp_facet(ncol = 2, scales = "free") 
sp

The levels or groups in the columns will be the facet titles of the charts. We can customize them with some custom css for the header. Again, make sure that the sp_facet() function is the last function in the chain.

custom_css_titles <- "background-color: grey; color: white;          
                      text-align: center; padding: 10px;         
                      border-radius: 5px;"

sp <- sp(
  data = penguins,
  mapping = spaes(x = flipper_length_mm, y = bill_length_mm),
  type = "points",
  facet_var = c("sex", "species"),
  include_legend = FALSE
) |> 
  sp_x_axis(rotation_axis_ticks = -90) |> 
  sp_title(custom_css = custom_css_titles) |> 
  SveltePlots::sp_facet(scales = "fixed") 

sp

Annotations

We can add annotations with the sp_add_segments, sp_add_arrows, and sp_add_text functions. The sp_add_segments function automatically adds a legend to the chart which we can click. If we do, there is a popup which we can drag around on the chart. That becomes useful if there are multiple segments on the chart whoich are overlapping and we would like to drag them into certain positions. A double click will make the popups disappear again.

data("purchases")
sp(
  data = purchases, type = "line",
  mapping = spaes(x = date, y = revenue_roll, group = age),
  colors = c("red", "green", "blue"),
  combine_same_groups = TRUE
) |>
  sp_add_series(
    data = purchases, 
    mapping = spaes(x = date, y = revenue, group = age),
    type = "points", 
    alpha = 0.4,
    tooltip = F, 
    include_legend = F
  ) |> 
    sp_add_series(
    data = purchases[purchases$revenue == max(purchases$revenue), ], 
    mapping = spaes(x = date, y = revenue, group = age),
    type = "points",
    size = 5, 
    tooltip = F
    ) |> 
  sp_add_segments(
    x_start = "2000-01-12", x_end = "2000-01-17",
    y_start = "auto", y_end ="auto",
    type = "rect", 
    opacity = 0.2,
    background_color = "black",
    text_color = "white",
    show_legend = TRUE, 
    legend_text = "Highest Revenue Day",
    tooltip = "Revenue: <strong>$13179</strong>"
  ) |> 
  sp_add_arrows(
    x_start = c("2000-03-01", "2000-03-01"), x_end = c("2000-01-15", "2000-01-15"),
    y_start = c(8000, 12000), y_end = c(10000, 13000),
    arrow_head = c(0, 0),
    size = c(200, 200), 
    curvature = c(0.2, 0.4), 
    direction = c("downward", "downward"), 
    color = c("black", "black"),
    arrow_head_type = c("triangle", "triangle")
  ) |> 
  sp_add_text(
    x = c("2000-02-01", "2000-02-20"),
    y = c(12500, 8500),
    text = c(
      "This was the highest revenue day",
      "Window of Some Event Happening"
    )
  ) 

Segments

If we click on the letter I, we can see a lot more popups which we can drag around on the chart to see to which event they correspnd to.

data("segments")
data("dau")

head(segments)
#> # A tibble: 6 × 6
#>   event_type start_date end_date   extra_details                    colors   key
#>   <chr>      <date>     <date>     <chr>                            <chr>  <dbl>
#> 1 a          2022-11-25 2022-11-29 Some Extra Details About the Ev… #8c56…     1
#> 2 a          2022-12-16 2022-12-30 Some Extra Details About the Ev… #8c56…     2
#> 3 a          2023-02-15 2023-03-01 Some Extra Details About the Ev… #8c56…     3
#> 4 b          2023-05-29 2023-06-21 Some Extra Details About the Ev… #1f77…     4
#> 5 c          2023-05-30 2023-06-01 Some Extra Details About the Ev… #98df…     5
#> 6 d          2023-05-31 2023-07-04 Some Extra Details About the Ev… #2ca0…     6
sp <- sp(
  data = dau, 
  type = "line",
  spaes(x = date, y = DAU), 
  tooltip = FALSE
) |> 
  sp_add_series(
    data = dau,
    mapping = spaes(x = date, y = DAU),
    type = "points",
    size = 4,
    tooltip = TRUE,
  ) |> 
  sp_add_segments(
    x_start = segments$start_date, 
    x_end = segments$end_date,
    y_start = "even",
    y_end = "even",
    type = "rect", 
    opacity = 0.2, 
    background_color = segments$colors,
    text_color = "white",
    show_legend = TRUE,
    legend_text = segments$event_type,
    tooltip = unlist(segments$extra_details),
    key = segments$key
  ) |> 
  sp_title("DAU", font_size = 24) |> 
  sp_x_axis(rotation_axis_ticks = -30) 

sp

Custom Tooltip

The custom tooltip works if we have a list column of tibbles named custom_tooltip. The chart will recognize the name and will use this column to create custom tooltips instead of using the y variable, retention in this case, for the tooltip. The column names for the individual tibbles will be displayed as the keys with the corresponding values.

data("quests")

quests <- quests |> 
  dplyr::rowwise() |>
  dplyr::mutate(
    custom_tooltip = dplyr::tibble(
      Installs = n.y,
      `Quest Start` = n.x,
      Retention = as.character(round(retention, 4)*100)
    ) |> list()
  ) |>
  dplyr::ungroup()

head(quests)
#> # A tibble: 6 × 6
#>   AB      n.x   n.y retention level custom_tooltip  
#>   <chr> <dbl> <dbl>     <dbl> <fct> <list>          
#> 1 a     25814 83435     0.309 1     <tibble [1 × 3]>
#> 2 b     25638 82929     0.309 1     <tibble [1 × 3]>
#> 3 b     18204 82929     0.220 49    <tibble [1 × 3]>
#> 4 a     17652 83435     0.212 49    <tibble [1 × 3]>
#> 5 b     16939 82929     0.204 11    <tibble [1 × 3]>
#> 6 a     16839 83435     0.202 11    <tibble [1 × 3]>
sp <- sp(
  data = quests,
  spaes(x = level, y = retention, group = AB),
  type = "line"
) |>
  sp_x_axis(rotation_axis_ticks = 90)

sp

Some More Examples With Different Data Sets

Walmart

The Walmart weekly sales data displays weekly revenue by department. We added points and lines series and a mix of manually added colors for department 1 and 3 and default colors for the other departments. We also rotated the x-axis and changed the labels for the y-axis to have aa dollar format. If you would like to explore the different formats which can be used you can check out the documentation.

data("walmart_sales_weekly")
walmart_sales_weekly <- walmart_sales_weekly |>
  dplyr::select(Dept, Date, Weekly_Sales) |>
  dplyr::arrange(Date) |>
  dplyr::as_tibble() |>
  dplyr::mutate(
    Date = lubridate::ymd(Date)
  )

sp(
  data = walmart_sales_weekly |>
    dplyr::filter(Dept %in% c(1, 3)),
  mapping = spaes(x = Date, y = Weekly_Sales, group = Dept),
  type = "line",
  colors = c("black", "grey")
) |>
  sp_add_series(
    data = walmart_sales_weekly |>
      dplyr::filter(Dept %in% c(38, 93, 95)),
    mapping = spaes(x = Date, y = Weekly_Sales, group = Dept),
    type = "line"
  ) |> 
  sp_add_series(
    data = walmart_sales_weekly |>
      dplyr::filter(Dept %in% c(8, 13)),
    mapping = spaes(x = Date, y = Weekly_Sales, group = Dept),
    type = "points"
  ) |> 
  sp_x_axis(rotation_axis_ticks = -30) |> 
  sp_y_axis(format = "$,.3r") 

CO2 Data

The charts below show case time-series data with adjustments for tooltips and axis.

data("CO2")
CO2 <- CO2 |>
  dplyr::as_tibble() |>
  dplyr::mutate(
    date = seq(
      as.Date("2023-01-01"),
      as.Date("2023-01-01") + lubridate::days(83), by = "day")
  )

sp(
  data = CO2, type = "line", 
  mapping = spaes(x = date, y = uptake, group = Type)
) |>
  sp_add_series(
    data = CO2,
    mapping = spaes(x = date, y = conc, group = Type),
    type = "line", tooltip = F
  ) |>
  sp_add_series(
    data = CO2, mapping = 
      spaes(x = date, y = conc, group = Type),
    type = "points"
  ) |>
  sp_x_axis(format = "%b-%d") 

Economics

data("economics")

sp(
  data = economics, 
  mapping = spaes(x = date, y = unemploy),
  type = "line",
  tooltip = T, 
  colors = "red"
) |>
  sp_add_series(
    data = economics,
    mapping = spaes(x = date, y = pce), 
    type = "line",
    tooltip = T, 
    colors = "green"
  ) |>
  sp_add_series(
    data = economics,
    mapping = spaes(x = date, y = psavert), 
    type = "line",
    tooltip = F, 
    colors = "blue"
  ) |> 
  sp_x_axis(
    format = "%b %Y", 
    ticks = 4,
    label = "Date",
    font_size_label = 14,
    font_size_ticks = 12,
    rotation_axis_ticks = -30
  ) |> 
  sp_y_axis(
    font_size_label = 14, 
    font_size_ticks = 12
  )

Hourly Time-Series

The chart below shows hourly data with a rotation of the x-axis tick labels.

# Generate hourly time series data for 7 days
set.seed(123)
start_time <- as.POSIXct("2022-01-01 00:00:00")
end_time <- start_time + 1 * 24 * 3600  # 7 days in seconds
timestamps <- seq(start_time, end_time, by = "hour")
values <- rnorm(length(timestamps))  # Random values for demonstration purposes

# Create a tibble
hourly_tibble <- tibble(
  timestamp = timestamps,
  value = values
)

sp(
  data = hourly_tibble, 
  mapping = spaes(x = timestamp, y = value),
  type = "line", 
  include_legend = FALSE
) |>  
  sp_x_axis(
    label = "Date",
    rotation_axis_ticks = 90,
    text_anchor = "end"
  )