| Title: | Data Visualisation Functions for Epidemiological Data Science Products |
|---|---|
| Description: | Tools for making epidemiological reporting easier with consistent static and dynamic charts and maps. Builds on 'ggplot2' for static visualizations as described in Wickham (2016) <doi:10.1007/978-3-319-24277-4> and 'plotly' for interactive visualizations as described in Sievert (2020) <doi:10.1201/9780429447273>. |
| Authors: | Harshana Liyanage [aut, cre] (ORCID: <https://orcid.org/0000-0001-9738-6349>), James Duke [aut], Alex Bhattacharya [aut] (ORCID: <https://orcid.org/0000-0003-3000-2771>), Liam Fitzpatrick [aut], James Leatherland [aut], Jordan Worth [aut], Emma Parker [aut], Jade Talbot [ctb] (ORCID: <https://orcid.org/0000-0001-6460-5170>), Karen Crawford [ctb], Frederick Sloots [ctb], Charlie Turner [ctb] |
| Maintainer: | Harshana Liyanage <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.1.2 |
| Built: | 2026-06-04 09:38:39 UTC |
| Source: | https://github.com/ukhsa-collaboration/epiviz |
This function creates an age-sex pyramid visualization, either as a static ggplot or an interactive plotly chart. The function can take either a line list (ungrouped data) or already grouped data as input. When using a line list, the function processes the data, groups it by age and sex, and then generates the pyramid. If grouped data is provided, it directly creates the pyramid.
age_sex_pyramid( dynamic = FALSE, base = NULL, params = list(df, var_map = list(age_var = "age", dob_var = "date_of_birth", sex_var = "sex", age_group_var = "age_group", value_var = "value", ci_lower = "ci_lower", ci_upper = "ci_upper"), mf_colours = c("#440154", "#2196F3"), x_breaks = 10, x_axis_title = "Number of cases", y_axis_title = "Age group (years)", text_size = 12, ci = NULL, ci_colour = "red", age_breakpoints = c(0, 5, 19, 65, Inf), age_calc_refdate = Sys.Date(), grouped = FALSE, legend_pos = "top", chart_title = "") )age_sex_pyramid( dynamic = FALSE, base = NULL, params = list(df, var_map = list(age_var = "age", dob_var = "date_of_birth", sex_var = "sex", age_group_var = "age_group", value_var = "value", ci_lower = "ci_lower", ci_upper = "ci_upper"), mf_colours = c("#440154", "#2196F3"), x_breaks = 10, x_axis_title = "Number of cases", y_axis_title = "Age group (years)", text_size = 12, ci = NULL, ci_colour = "red", age_breakpoints = c(0, 5, 19, 65, Inf), age_calc_refdate = Sys.Date(), grouped = FALSE, legend_pos = "top", chart_title = "") )
dynamic |
Logical. If |
base |
An optional base plot to add the pyramid to. Default is |
params |
A list of parameters including:
|
When grouped = FALSE, the function processes a line list by grouping the data by age and sex,
calculating age based on either the provided age column or date of birth, and then generating the age-sex pyramid.
When grouped = TRUE, it assumes the data is already grouped and uses the provided values directly to generate the pyramid.
A ggplot or plotly object representing the age-sex pyramid, depending on the value of dynamic.
# Example using a line list df <- epiviz::lab_data result <- age_sex_pyramid( dynamic = FALSE, params = list( df = df, var_map = list(dob_var = 'date_of_birth', sex_var = 'sex'), grouped = FALSE ) )# Example using a line list df <- epiviz::lab_data result <- age_sex_pyramid( dynamic = FALSE, params = list( df = df, var_map = list(dob_var = 'date_of_birth', sex_var = 'sex'), grouped = FALSE ) )
A function for producing either a static (ggplot) or dynamic (plotly) column chart.
col_chart( dynamic = FALSE, params = list(df = NULL, x = NULL, y = NULL, x_time_series = FALSE, x_time_series_bar_labels = FALSE, time_period = "day", group_var = NULL, group_var_barmode = "stack", fill_colours = "lightblue", bar_border_colour = "transparent", bar_labels = NULL, bar_labels_pos = "bar_above", bar_labels_font_size = 8, bar_labels_font_colour = "black", bar_labels_angle = 0, bar_labels_percent = FALSE, case_boxes = FALSE, case_boxes_colour = "white", axis_flip = FALSE, ci = NULL, ci_upper = NULL, ci_lower = NULL, ci_legend = TRUE, ci_legend_title = "Confidence interval", ci_colours = "red", errorbar_width = NULL, chart_title = NULL, chart_title_size = 13, chart_title_colour = "black", chart_footer = NULL, chart_footer_size = 12, chart_footer_colour = "black", x_axis_title = NULL, y_axis_title = NULL, x_axis_title_font_size = 11, y_axis_title_font_size = 11, x_axis_label_angle = NULL, y_axis_label_angle = NULL, x_axis_label_font_size = 9, y_axis_label_font_size = 9, x_limit_min = NULL, x_limit_max = NULL, y_limit_min = NULL, y_limit_max = NULL, x_axis_break_labels = NULL, y_axis_break_labels = NULL, x_axis_n_breaks = NULL, y_axis_n_breaks = NULL, x_axis_reverse = FALSE, y_percent = FALSE, show_gridlines = TRUE, show_axislines = TRUE, legend_title = "", legend_pos = "right", legend_font_size = 8, legend_title_font_size = 8, hline = NULL, hline_colour = "black", hline_width = 0.5, hline_type = "dashed", hline_label = NULL, hline_label_colour = "black", hover_labels = NULL) )col_chart( dynamic = FALSE, params = list(df = NULL, x = NULL, y = NULL, x_time_series = FALSE, x_time_series_bar_labels = FALSE, time_period = "day", group_var = NULL, group_var_barmode = "stack", fill_colours = "lightblue", bar_border_colour = "transparent", bar_labels = NULL, bar_labels_pos = "bar_above", bar_labels_font_size = 8, bar_labels_font_colour = "black", bar_labels_angle = 0, bar_labels_percent = FALSE, case_boxes = FALSE, case_boxes_colour = "white", axis_flip = FALSE, ci = NULL, ci_upper = NULL, ci_lower = NULL, ci_legend = TRUE, ci_legend_title = "Confidence interval", ci_colours = "red", errorbar_width = NULL, chart_title = NULL, chart_title_size = 13, chart_title_colour = "black", chart_footer = NULL, chart_footer_size = 12, chart_footer_colour = "black", x_axis_title = NULL, y_axis_title = NULL, x_axis_title_font_size = 11, y_axis_title_font_size = 11, x_axis_label_angle = NULL, y_axis_label_angle = NULL, x_axis_label_font_size = 9, y_axis_label_font_size = 9, x_limit_min = NULL, x_limit_max = NULL, y_limit_min = NULL, y_limit_max = NULL, x_axis_break_labels = NULL, y_axis_break_labels = NULL, x_axis_n_breaks = NULL, y_axis_n_breaks = NULL, x_axis_reverse = FALSE, y_percent = FALSE, show_gridlines = TRUE, show_axislines = TRUE, legend_title = "", legend_pos = "right", legend_font_size = 8, legend_title_font_size = 8, hline = NULL, hline_colour = "black", hline_width = 0.5, hline_type = "dashed", hline_label = NULL, hline_label_colour = "black", hover_labels = NULL) )
dynamic |
Logical indicating whether to produce a dynamic (plotly) output.
Default is |
params |
A named list containing arguements used to create the plot.
|
A ggplot or plotly object.
# Basic column chart library(epiviz) library(dplyr) detections_by_region <- lab_data |> filter(specimen_date >= as.Date("2023-01-01") & specimen_date <= as.Date("2023-12-31")) |> group_by(region) |> summarise(detections = n()) |> ungroup() my_chart <- col_chart( params = list( df = detections_by_region, x = "region", y = "detections", fill_colours = "#007C91", chart_title = "Laboratory Detections by Region 2023", x_axis_title = "Region", y_axis_title = "Number of detections" ) )# Basic column chart library(epiviz) library(dplyr) detections_by_region <- lab_data |> filter(specimen_date >= as.Date("2023-01-01") & specimen_date <= as.Date("2023-12-31")) |> group_by(region) |> summarise(detections = n()) |> ungroup() my_chart <- col_chart( params = list( df = detections_by_region, x = "region", y = "detections", fill_colours = "#007C91", chart_title = "Laboratory Detections by Region 2023", x_axis_title = "Region", y_axis_title = "Number of detections" ) )
A function for producing either a static (ggplot) or dynamic (plotly) epidemic curve.
epi_curve( dynamic = FALSE, params = list(df = NULL, y = NULL, date_var = NULL, date_start = NULL, date_end = NULL, time_period = "day", group_var = NULL, group_var_barmode = "stack", fill_colours = "lightblue", bar_border_colour = "transparent", case_boxes = FALSE, case_boxes_colour = "white", rolling_average_line = FALSE, rolling_average_line_lookback = 7, rolling_average_line_colour = "red", rolling_average_line_width = 1, rolling_average_line_legend_label = "Rolling average", cumulative_sum_line = FALSE, cumulative_sum_line_colour = "darkblue", cumulative_sum_line_width = 1, cumulative_sum_line_legend_label = "Cumulative sum", cumulative_sum_line_axis_title = "Cumulative Sum", chart_title = NULL, chart_title_size = 13, chart_title_colour = "black", chart_footer = NULL, chart_footer_size = 12, chart_footer_colour = "black", x_axis_title = NULL, y_axis_title = NULL, x_axis_title_font_size = 11, y_axis_title_font_size = 11, x_axis_label_angle = NULL, y_axis_label_angle = NULL, x_axis_label_font_size = 9, y_axis_label_font_size = 9, y_limit_min = NULL, y_limit_max = NULL, x_axis_break_labels = NULL, y_axis_break_labels = NULL, y_axis_n_breaks = NULL, show_gridlines = FALSE, show_axislines = TRUE, legend_title = "", legend_pos = "right", legend_font_size = 8, legend_title_font_size = 8, hline = NULL, hline_colour = "black", hline_width = 0.5, hline_type = "dashed", hline_label = NULL, hline_label_colour = "black", hover_labels = NULL) )epi_curve( dynamic = FALSE, params = list(df = NULL, y = NULL, date_var = NULL, date_start = NULL, date_end = NULL, time_period = "day", group_var = NULL, group_var_barmode = "stack", fill_colours = "lightblue", bar_border_colour = "transparent", case_boxes = FALSE, case_boxes_colour = "white", rolling_average_line = FALSE, rolling_average_line_lookback = 7, rolling_average_line_colour = "red", rolling_average_line_width = 1, rolling_average_line_legend_label = "Rolling average", cumulative_sum_line = FALSE, cumulative_sum_line_colour = "darkblue", cumulative_sum_line_width = 1, cumulative_sum_line_legend_label = "Cumulative sum", cumulative_sum_line_axis_title = "Cumulative Sum", chart_title = NULL, chart_title_size = 13, chart_title_colour = "black", chart_footer = NULL, chart_footer_size = 12, chart_footer_colour = "black", x_axis_title = NULL, y_axis_title = NULL, x_axis_title_font_size = 11, y_axis_title_font_size = 11, x_axis_label_angle = NULL, y_axis_label_angle = NULL, x_axis_label_font_size = 9, y_axis_label_font_size = 9, y_limit_min = NULL, y_limit_max = NULL, x_axis_break_labels = NULL, y_axis_break_labels = NULL, y_axis_n_breaks = NULL, show_gridlines = FALSE, show_axislines = TRUE, legend_title = "", legend_pos = "right", legend_font_size = 8, legend_title_font_size = 8, hline = NULL, hline_colour = "black", hline_width = 0.5, hline_type = "dashed", hline_label = NULL, hline_label_colour = "black", hover_labels = NULL) )
dynamic |
Logical indicating whether to produce a dynamic (plotly) output.
Default is |
params |
A named list containing arguments used to create the plot.
|
A ggplot or plotly object.
# Basic epi curve example library(epiviz) basic_epi_curve <- epi_curve( params = list( df = lab_data, date_var = "specimen_date", date_start = "2020-01-01", date_end = "2023-12-31", time_period = "year_month", fill_colours = "#007C91", chart_title = "Laboratory Detections per Month", x_axis_title = "Year - Month", y_axis_title = "Number of detections" ) )# Basic epi curve example library(epiviz) basic_epi_curve <- epi_curve( params = list( df = lab_data, date_var = "specimen_date", date_start = "2020-01-01", date_end = "2023-12-31", time_period = "year_month", fill_colours = "#007C91", chart_title = "Laboratory Detections per Month", x_axis_title = "Year - Month", y_axis_title = "Number of detections" ) )
A function for producing either static (ggplot) or dynamic (leaflet) choropleth maps.
epi_map( dynamic = FALSE, params = list(df = NULL, value_col = NULL, data_areacode = NULL, inc_shp = TRUE, shp_name = NULL, shp_areacode = NULL, fill_palette = "Blues", fill_opacity = 1, break_intervals = NULL, break_labels = NULL, force_cat = TRUE, n_breaks = NULL, labels = NULL, map_title = "", map_title_size = 13, map_title_colour = "black", map_footer = "", map_footer_size = 12, map_footer_colour = "black", area_labels = FALSE, area_labels_topn = NULL, legend_title = "", legend_pos = "topright", map_zoom = NULL, border_shape_name = NULL, border_code_col = NULL, border_areaname = NULL) )epi_map( dynamic = FALSE, params = list(df = NULL, value_col = NULL, data_areacode = NULL, inc_shp = TRUE, shp_name = NULL, shp_areacode = NULL, fill_palette = "Blues", fill_opacity = 1, break_intervals = NULL, break_labels = NULL, force_cat = TRUE, n_breaks = NULL, labels = NULL, map_title = "", map_title_size = 13, map_title_colour = "black", map_footer = "", map_footer_size = 12, map_footer_colour = "black", area_labels = FALSE, area_labels_topn = NULL, legend_title = "", legend_pos = "topright", map_zoom = NULL, border_shape_name = NULL, border_code_col = NULL, border_areaname = NULL) )
dynamic |
Logical indicating whether to produce a dynamic (leaflet) output.
Default is |
params |
A named list containing arguements used in map.
|
A ggplot or leaflet object.
# Basic epi_map example library(epiviz) library(dplyr) # Prepare data London_staph_detections <- lab_data |> filter(region == "London", organism_species_name == "STAPHYLOCOCCUS AUREUS") |> group_by(local_authority_name) |> summarise(detections = n()) # Create static map my_map <- epi_map( params = list( df = London_staph_detections, value_col = "detections", data_areacode = "local_authority_name", inc_shp = FALSE, shp_name = London_LA_boundaries_2023, shp_areacode = "LAD23NM", map_title = "Staphylococcus Aureus detections in London", legend_title = "Detections" ) )# Basic epi_map example library(epiviz) library(dplyr) # Prepare data London_staph_detections <- lab_data |> filter(region == "London", organism_species_name == "STAPHYLOCOCCUS AUREUS") |> group_by(local_authority_name) |> summarise(detections = n()) # Create static map my_map <- epi_map( params = list( df = London_staph_detections, value_col = "detections", data_areacode = "local_authority_name", inc_shp = FALSE, shp_name = London_LA_boundaries_2023, shp_areacode = "LAD23NM", map_title = "Staphylococcus Aureus detections in London", legend_title = "Detections" ) )
A dataset containing synthetic lab data for epidemiological visualisation purposes.
data(lab_data)data(lab_data)
A data frame with the following columns:
Date of birth of the patients.
Gender of the patients (Factor with levels: "Female", "Male").
Organism species name (Factor with levels: "KLEBSIELLA PNEUMONIAE").
Date of specimen collection.
Laboratory codes (Factor with unique levels).
Name of the local authority.
Code of the local authority.
Name of UKHSA regions.
data(lab_data) head(lab_data)data(lab_data) head(lab_data)
This function generates a line chart from a data frame using specified x and y variables. Optionally, the plot can be rendered as an interactive Plotly object. The function also allows grouping of data based on a specified grouping variable.
line_chart( dynamic = FALSE, base = NULL, params = list(df, x, y, ci = NULL, lower = NULL, upper = NULL, error_colour = c("#f2c75c"), group_var, line_colour = c("blue"), line_type = "solid", width = 1, title = NULL, x_label = NULL, x_label_angle = NULL, y_label = NULL, y_label_angle = NULL, y_percent = FALSE, st_theme = NULL, add_points = FALSE, show_gridlines = FALSE, show_axislines = TRUE, legend_title = NULL, legend_position = NULL, hline = NULL, hline_colour = "red", hline_label = NULL), ... )line_chart( dynamic = FALSE, base = NULL, params = list(df, x, y, ci = NULL, lower = NULL, upper = NULL, error_colour = c("#f2c75c"), group_var, line_colour = c("blue"), line_type = "solid", width = 1, title = NULL, x_label = NULL, x_label_angle = NULL, y_label = NULL, y_label_angle = NULL, y_percent = FALSE, st_theme = NULL, add_points = FALSE, show_gridlines = FALSE, show_axislines = TRUE, legend_title = NULL, legend_position = NULL, hline = NULL, hline_colour = "red", hline_label = NULL), ... )
dynamic |
A logical value. If |
base |
A base plotly or ggplot2 object to add the line chart to. Default is |
params |
A list containing the following elements:
|
... |
Additional arguments passed to |
A plotly or ggplot2 object representing the line chart.
library(dplyr) library(epiviz) # Prepare data test_df <- epiviz::lab_data test_df$specimen_date <- as.Date(test_df$specimen_date) summarised_df <- test_df |> filter(specimen_date >= as.Date("2023-01-01") & specimen_date <= as.Date("2023-12-31")) |> group_by(organism_species_name, specimen_date) |> summarize(count = n(), .groups = 'drop') # Create params list params <- list( df = as.data.frame(summarised_df), x = "specimen_date", y = "count", group_var = "organism_species_name", line_colour = c("blue", "green", "orange") ) # Generate static line chart result <- line_chart(params = params, dynamic = FALSE)library(dplyr) library(epiviz) # Prepare data test_df <- epiviz::lab_data test_df$specimen_date <- as.Date(test_df$specimen_date) summarised_df <- test_df |> filter(specimen_date >= as.Date("2023-01-01") & specimen_date <= as.Date("2023-12-31")) |> group_by(organism_species_name, specimen_date) |> summarize(count = n(), .groups = 'drop') # Create params list params <- list( df = as.data.frame(summarised_df), x = "specimen_date", y = "count", group_var = "organism_species_name", line_colour = c("blue", "green", "orange") ) # Generate static line chart result <- line_chart(params = params, dynamic = FALSE)
This function interprets a given data frame or ggplot visualisation by sending it to a language model API via the ellmer package. It supports multiple LLM providers, allowing users to specify the desired provider and model through environment variables.
llm_interpret(input, word_limit = 100, prompt_extension = NULL)llm_interpret(input, word_limit = 100, prompt_extension = NULL)
input |
An input object, either a data frame or a ggplot object, representing the data or visualisation to be interpreted. |
word_limit |
Integer. The desired word length for the response. Defaults to 100. |
prompt_extension |
Character. Optional additional instructions to extend the standard prompt. Defaults to NULL. |
Supported LLM Providers and Models:
OpenAI: Utilises OpenAI's models via chat_openai(). Requires setting the OPENAI_API_KEY environment variable. Applicable models include:
"gpt-4.1-nano"
Google Gemini: Utilises Google's Gemini models via chat_gemini(). Requires setting the GOOGLE_API_KEY environment variable. Applicable models include:
"gemini-2.5-flash-lite"
Anthropic Claude: Utilises Anthropic's Claude models via chat_anthropic(). Requires setting the CLAUDE_API_KEY environment variable. Applicable models include:
"claude-sonnet-4-20250514"
Environment Variables:
LLM_PROVIDER: Specifies the LLM provider ("openai", "gemini", "anthropic").
LLM_API_KEY: The API key corresponding to the chosen provider.
LLM_MODEL: The model identifier to use.
Note: Ensure that the appropriate environment variables are set before invoking this function. The function will throw an error if the specified provider is unsupported or if required environment variables are missing.
A character string containing the narrative or interpretation of the input object as generated by the LLM.
As of October 2025, this function has been tested and verified to work with the following models:
OpenAI: gpt-4.1-nano
Anthropic: claude-sonnet-4-20250514
Google Gemini: gemini-2.5-flash-lite
Additional models may be tested in the future. Users can provide custom instructions
through the prompt_extension parameter for specialised analysis requirements.
A function for producing either static (ggplot) or dynamic (plotly) point charts.
point_chart( dynamic = FALSE, base = NULL, params = list(df = NULL, x = NULL, y = NULL, point_shape = "triangle", point_size = 1.5, point_colours = "blue", point_labels = NULL, point_labels_size = 5, point_labels_hjust = 0, point_labels_vjust = 0, point_labels_nudge_x = 0, point_labels_nudge_y = 0, group_var = NULL, ci = NULL, ci_upper = NULL, ci_lower = NULL, ci_legend = TRUE, ci_legend_title = "Confidence interval", ci_colours = "red", errorbar_width = NULL, y_sec_axis = FALSE, y_sec_axis_no_shift = TRUE, y_sec_axis_percent_full = FALSE, chart_title = NULL, chart_title_size = 13, chart_title_colour = "black", chart_footer = NULL, chart_footer_size = 12, chart_footer_colour = "black", x_axis_title = NULL, y_axis_title = NULL, x_axis_title_font_size = 11, y_axis_title_font_size = 11, x_axis_label_angle = NULL, y_axis_label_angle = NULL, x_axis_label_font_size = 9, y_axis_label_font_size = 9, x_axis_reverse = FALSE, y_percent = FALSE, x_limit_min = NULL, x_limit_max = NULL, y_limit_min = NULL, y_limit_max = NULL, x_axis_break_labels = NULL, y_axis_break_labels = NULL, x_axis_n_breaks = NULL, y_axis_n_breaks = NULL, x_axis_date_breaks = NULL, st_theme = NULL, show_gridlines = TRUE, show_axislines = TRUE, legend_title = "", legend_pos = "right", legend_font_size = 8, legend_title_font_size = 8, point_size_legend = FALSE, point_size_legend_title = "", hline = NULL, hline_colour = "black", hline_width = 0.5, hline_type = "dashed", hline_label = NULL, hline_label_colour = "black") )point_chart( dynamic = FALSE, base = NULL, params = list(df = NULL, x = NULL, y = NULL, point_shape = "triangle", point_size = 1.5, point_colours = "blue", point_labels = NULL, point_labels_size = 5, point_labels_hjust = 0, point_labels_vjust = 0, point_labels_nudge_x = 0, point_labels_nudge_y = 0, group_var = NULL, ci = NULL, ci_upper = NULL, ci_lower = NULL, ci_legend = TRUE, ci_legend_title = "Confidence interval", ci_colours = "red", errorbar_width = NULL, y_sec_axis = FALSE, y_sec_axis_no_shift = TRUE, y_sec_axis_percent_full = FALSE, chart_title = NULL, chart_title_size = 13, chart_title_colour = "black", chart_footer = NULL, chart_footer_size = 12, chart_footer_colour = "black", x_axis_title = NULL, y_axis_title = NULL, x_axis_title_font_size = 11, y_axis_title_font_size = 11, x_axis_label_angle = NULL, y_axis_label_angle = NULL, x_axis_label_font_size = 9, y_axis_label_font_size = 9, x_axis_reverse = FALSE, y_percent = FALSE, x_limit_min = NULL, x_limit_max = NULL, y_limit_min = NULL, y_limit_max = NULL, x_axis_break_labels = NULL, y_axis_break_labels = NULL, x_axis_n_breaks = NULL, y_axis_n_breaks = NULL, x_axis_date_breaks = NULL, st_theme = NULL, show_gridlines = TRUE, show_axislines = TRUE, legend_title = "", legend_pos = "right", legend_font_size = 8, legend_title_font_size = 8, point_size_legend = FALSE, point_size_legend_title = "", hline = NULL, hline_colour = "black", hline_width = 0.5, hline_type = "dashed", hline_label = NULL, hline_label_colour = "black") )
dynamic |
Logical indicating whether to produce a dynamic (plotly) output.
Default is |
base |
A base ggplot or plotly object that the output will be applied to. If
|
params |
A named list containing arguements used to create the plot. '
|
A ggplot or plotly object.
# Basic point chart example library(epiviz) library(dplyr) detections_per_month <- epiviz::lab_data |> group_by(specimen_month = lubridate::floor_date(specimen_date, 'month')) |> summarise(detections = n()) |> ungroup() # Create static point chart my_chart <- point_chart( params = list( df = detections_per_month, x = "specimen_month", y = "detections", point_colours = "#007C91", point_size = 3, chart_title = "Detections per Month", x_axis_title = "Month", y_axis_title = "Number of detections" ) )# Basic point chart example library(epiviz) library(dplyr) detections_per_month <- epiviz::lab_data |> group_by(specimen_month = lubridate::floor_date(specimen_date, 'month')) |> summarise(detections = n()) |> ungroup() # Create static point chart my_chart <- point_chart( params = list( df = detections_per_month, x = "specimen_month", y = "detections", point_colours = "#007C91", point_size = 3, chart_title = "Detections per Month", x_axis_title = "Month", y_axis_title = "Number of detections" ) )