Skip to contents

Terms

The following terms are used in the CVDPrevent API to describe key concepts:

Term Description Example
System Level Grouping of Areas into comparable levels England, Region, ICB, sub-ICB
Area Geographical locality for which data was recorded Bedfordshire, Luton and Milton Keynes ICB
Time Period Time span in which data was recorded To June 2024
Indicator High-level performance measure CVDP001AF is short reference for “Prevalence of GP recorded atrial fibrillation” indicator
Metric Category breakdown of Indicator CVDP001AF - Male, Aged 18-39

System Levels by Time Period

You can use cvd_time_period_system_levels() to explore which system levels are reported in each time period. These levels may vary over time due to changes in NHS geography - for example, Sustainability and Transformation Partnerships (STPs) were later replaced by Integrated Care Systems (ICS / ICBs).1

The following code snippet creates a table showing which system levels are available for each reporting time period. A ✔️ indicates that data for that system level is available in the corresponding period.

cvd_time_period_system_levels() |>
  dplyr::select(dplyr::any_of(c(
    "TimePeriodID",
    "TimePeriodName",
    "SystemLevelName"
  ))) |>
  dplyr::mutate(value_show = "✔️") |>
  tidyr::pivot_wider(
    names_from = dplyr::any_of("SystemLevelName"),
    values_from = dplyr::any_of("value_show"),
    values_fill = ""
  ) |>
  gt::gt() |>
  gt::tab_options(quarto.disable_processing = TRUE) |>
  gt::cols_align(
    align = "center",
    columns = c(
      dplyr::everything(),
      -dplyr::any_of(c("TimePeriodName"))
    )
  )
TimePeriodID TimePeriodName England STP CCG PCN Practice Region ICB Sub-ICB
1 To March 2020 ✔️ ✔️ ✔️ ✔️ ✔️
2 To March 2021 ✔️ ✔️ ✔️ ✔️ ✔️
3 To September 2021 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
4 To March 2022 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
5 To June 2022 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
6 To September 2022 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
7 To December 2022 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
8 To March 2023 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
9 To June 2023 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
10 To September 2023 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
11 Jan 2022 - Dec 2022 ✔️ ✔️ ✔️
12 Apr 2022 - Mar 2023 ✔️ ✔️ ✔️
13 Oct 2022 - Sep 2023 ✔️ ✔️ ✔️
14 Jul 2022 - Jun 2023 ✔️ ✔️ ✔️
15 To December 2023 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
16 Jan 2023 - Dec 2023 ✔️ ✔️ ✔️
17 To March 2024 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
18 To June 2024 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
19 Apr 2023 - Mar 2024 ✔️ ✔️ ✔️
20 To September 2024 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
21 Jul 2023 - Jun 2024 ✔️ ✔️ ✔️
22 To December 2024 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
23 Oct 2023 - Sep 2024 ✔️ ✔️ ✔️
24 To March 2025 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
25 Jan 2024 - Dec 2024 ✔️ ✔️ ✔️
26 To June 2025 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
27 Apr 2024 - Mar 2025 ✔️ ✔️ ✔️

What this does:

  • Selects relevant columns: Time period and system level names

  • Adds a marker: A check-mark to indicate presence

  • Reshapes the data: Converts long format to wide, with system levels as columns

  • Displays the result: Uses {gt} to render a clean, readable table

Listing areas

When working with areas, the first step is to identify the time period you are interested in. This is important because:

  • areas can change over time. For example, an area reported in time period 1 may no longer exist in time period 21 (such as STP in the above table).

  • certain system levels are excluded from specific reports. For instance, the annual report covering Jan 2022 - Dec 2022 (time period id = 11) does not include PCN, Practice or Sub-ICB level data.

To explore available areas, a recommended function is cvd_area_list(). This requires you to specify both the time period and either a system_level_id or a parent_area_id.

Using system_level_id will return all areas within the chosen time_period_id that share the same system level. For example, to list all NHS Regions (system_level_id = 6) available in time period 22:

cvd_area_list(time_period_id = 22, system_level_id = 6) |>
  dplyr::select(dplyr::any_of(c(
    "SystemLevelID",
    "SystemLevelName",
    "AreaName"
  ))) |>
  gt::gt() |>
  gt::tab_options(quarto.disable_processing = TRUE)
SystemLevelID SystemLevelName AreaName
6 Region East of England
6 Region London
6 Region Midlands
6 Region North East and Yorkshire
6 Region North West
6 Region South East
6 Region South West

Alternatively, if you already know the area you’re interested in, you can use cvd_area_search(). This function searches by partial area name and returns all matches for the specified time period.

For example, to find all areas containing the word “acorn” in time period 22:

cvd_area_search(partial_area_name = "acorn", time_period_id = 22) |>
  dplyr::select(dplyr::any_of(c("AreaID", "AreaName"))) |>
  gt::gt() |>
  gt::tab_options(quarto.disable_processing = TRUE)
AreaID AreaName
4302 Acorn Group Practice
3238 Acorn Medical Centre
2444 Acorn Medical Practice
2669 Acorn Surgery
4037 The Acorn & Gaumont House Surgery

Listing indicators

To work with indicators, you first need to identify both the time period and the system level of interest. This is important because not all indicators are available at every system level. For example, some indicators are not reported for PCN or Practice levels.

The following example demonstrates how to list indicators available for each system level in time period 26.

# get details for system levels and time periods
syst_levels <- cvd_area_system_level_time_periods()

# get a summary of system level ids and names
df_syst_levels <-
  syst_levels |>
  dplyr::filter(TimePeriodID == 26) |>
  dplyr::select(dplyr::any_of(c("SystemLevelID", "SystemLevelName")))

# iterate over all system levels available at time period id 26 and gather the indicators
df_indicators_syst_level <-
  purrr::map2_df(
    .x = df_syst_levels$SystemLevelID,
    .y = df_syst_levels$SystemLevelName,
    .f = \(.x, .y) {
      cvd_indicator_list(time_period_id = 26, system_level_id = .x) |>
        dplyr::select(dplyr::any_of(c("IndicatorID", "IndicatorShortName"))) |>
        dplyr::mutate(SystemLevelName = .y)
    }
  )

# pivot the table to list system level
df_indicators_syst_level |>
  dplyr::mutate(value_show = "✔️") |>
  tidyr::pivot_wider(
    names_from = dplyr::any_of("SystemLevelName"),
    values_from = dplyr::any_of("value_show"),
    values_fill = ""
  ) |>
  gt::gt() |>
  gt::tab_options(quarto.disable_processing = TRUE) |>
  gt::cols_align(
    align = "center",
    columns = c(
      gt::everything(),
      -gt::any_of(c("IndicatorShortName"))
    )
  ) |>
  gt::tab_header(
    title = gt::md("Indicators for *Time Period 26* by system level")
  )
Indicators for Time Period 26 by system level
IndicatorID IndicatorShortName England PCN Practice Region ICB Sub-ICB
1 AF: Prevalence (CVDP001AF) ✔️ ✔️ ✔️ ✔️
2 Hypertension: Treated to appropriate threshold (age < 80) (CVDP002HYP) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
3 Hypertension: Treated to appropriate threshold (age >= 80) (CVDP003HYP) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
4 Hypertension: BP monitoring (CVDP004HYP) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
7 AF: Treated with anticoagulants (CVDP002AF) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
8 CKD: Prevalence (CVDP001CKD) ✔️ ✔️ ✔️ ✔️
9 FH: Possible, probable and confirmed prevalence (CVDP002FH) ✔️ ✔️ ✔️ ✔️
10 FH: Genetically confirmed prevalence (CVDP003FH) ✔️ ✔️ ✔️
11 Hypertension: Prevalence (CVDP001HYP) ✔️ ✔️ ✔️ ✔️
12 CVD: Prevalence (CVDP001CVD) ✔️ ✔️ ✔️ ✔️
13 CKD: Uncoded - two low eGFRs with no recorded CKD (CVDP002CKD) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
14 Cholesterol: QRISK >= 20% treated with LLT (CVDP003CHOL) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
15 CKD: High risk - one low eGFR with no recorded CKD (CVDP003CKD) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
17 CKD: Monitoring with ACR (CVDP004CKD) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
18 FH: Cholesterol in at risk range for FH with no investigation for FH (CVDP004FH) ✔️ ✔️ ✔️ ✔️
19 CKD: High risk treated with RAS antagonists (CVDP005CKD) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
20 Hypertension: High risk – one high BP with no recorded hypertension (CVDP005HYP) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
21 Hypertension: Potential antihypertensive overtreatment (CVDP006HYP) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
22 Cholesterol: QRISK >= 10% treated with LLT (CVDP006CHOL) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
23 Cholesterol: CKD treated with LLT (CVDP010CHOL) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
24 Smoking: Record of smoking status (CVDP001SMOK) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
25 NDH: High risk – one HbA1c 42-48 mmol/mol, with no recorded NDH or DM (CVDP002NDH) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
26 Smoking: Current smokers offered support/treatment (CVDP002SMOK) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
27 DM: Uncoded - two high HbA1c with no recorded diabetes (CVDP003DM) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
28 DM: High risk - one high HbA1c with no recorded diabetes (CVDP005DM) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
29 CKD: Monitoring with eGFR (CVDP006CKD) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
31 CKD: ACR < 70mg/mmol treated to appropriate BP threshold (CVDP007CKD) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
32 Hypertension: Treated to appropriate threshold (all ages) (CVDP007HYP) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
33 Cholesterol: Primary prevention of CVD treated with LLT (CVDP008CHOL) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
34 Cholesterol: CVD treated with LLT (CVDP009CHOL) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
45 BMI: Record of BMI status (CVDP001BMI) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
46 HF: Prevalence (CVD001HF) ✔️ ✔️ ✔️ ✔️
47 HF: Monitoring with eGFR (CVD002HF) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
48 CHD: Treated to BP threshold (CVDP002CHD) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
49 Stroke: Treatment to BP threshold (CVDP002STRK) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
50 AF: Low risk AF with recorded CHA2DS2-VASc score (CVDP004AF) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
51 AF: Treated with anticoagulants - DOAC prioritised (CVDP005AF) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
52 Hypertension: Monitoring with ACR (CVDP009HYP) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
53 Cholesterol: CVD cholesterol monitoring (CVDP011CHOL) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
54 Cholesterol: CVD treated to cholesterol threshold (CVDP012CHOL) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️

What this does:

  • Retrieve all system levels and time periods

  • Filter the system levels available in time period 26

  • For each system level, collect the list of indicators

  • Pivot the results into a table that clearly shows which indicators are available at each system level

The resulting table provides a quick overview of indicator coverage across system levels, making it easy to spot where gaps exist.

Listing metrics

Metrics provide breakdowns of indicator performance by demographic categories such as sex, age group or ethnicity. They allow you to explore how an indicator varies across different population subgroups.

The function cvd_indicator_metric_list() retrieves metrics for all indicators within a specified time period and system level.

The example below shows how to list all metrics available for the indicator AF: Prevalence (CVDP01AF) (Indicator ID = 1) in time period 26 at the England system level:

cvd_indicator_metric_list(time_period_id = 26, system_level_id = 1) |>
  dplyr::filter(IndicatorID == 1) |>
  dplyr::select(dplyr::any_of(c(
    "MetricCategoryTypeName",
    "Indicator",
    "MetricCategoryName",
    "CategoryAttribute",
    "MetricID"
  ))) |>
  dplyr::group_by(MetricCategoryTypeName) |>
  dplyr::arrange(MetricCategoryName, .by_group = TRUE) |>
  gt::gt(row_group_as_column = TRUE) |>
  gt::tab_options(quarto.disable_processing = TRUE) |>
  gt::tab_stubhead(label = "MetricCategoryTypeName") |>
  gt::tab_header(
    title = gt::md(
      "**Metrics** for *Indicator 1 (AF: Prevalence)* in *Time Period 26* and for the *England* system level"
    )
  )
Metrics for Indicator 1 (AF: Prevalence) in Time Period 26 and for the England system level
MetricCategoryTypeName MetricCategoryName CategoryAttribute MetricID
Age group 18-39 Male 177
18-39 Female 180
18-39 Persons 186
40-59 Female 173
40-59 Male 175
40-59 Persons 187
60-79 Female 176
60-79 Male 179
60-79 Persons 188
80+ Male 174
80+ Female 178
80+ Persons 189
Deprivation quintile 1 - most deprived Persons 182
2 Persons 183
3 Persons 181
4 Persons 184
5 - least deprived Persons 185
Deprivation quintile - Age Standardised 1 - most deprived Persons 863
2 Persons 864
3 Persons 865
4 Persons 866
5 - least deprived Persons 867
Sex Female Female 171
Male Male 172
Persons Persons 190
Sex - Age Standardised Female Female 862
Male Male 861
Persons Persons 868

Understanding Metric Categories

Common categories include:

  • Age group

  • Deprivation quintile

  • Sex

Age-standardised metrics: for some indicators, age-standardised versions of these categories are also available.

Sex disaggregation: certain metrics are further broken down by sex. For example, in the table above, the age group 18-39 is reported both for all persons in that group (CategoryAttribute = Person) and separately for Male and Female subgroups.

Summary

Together, these terms form the foundation of the CVDPrevent API and provide a consistent language for working with cardiovascular data. By clearly defining system levels, areas, time periods, indicators and metrics the API enables users to navigate complex datasets with confidence, compare performance across different contexts and explore meaningful demographic breakdowns. Understanding these concepts is an essential first step before making use of the wider functionality demonstrated in this vignette.