bolster.data_sources.health_ni.disease_prevalence

NISRA Disease Prevalence Module.

Provides access to Northern Ireland’s disease prevalence statistics from GP clinical disease registers (Quality & Outcomes Framework, QOF). Data are released annually after National Prevalence Day.

Data Coverage:
  • Financial years 2017/18 to present (extended annually)

  • NI-level: registered patients per disease register and prevalence per 1,000 patients

  • By Local Government District (LGD): same metrics per council

  • By HSC Trust: same metrics per Trust

  • By GP practice (Table 5, Excel): ~305–360 practices, 2009/10 to present

Disease Registers (17):

Asthma, Atrial Fibrillation, Cancer, Chronic Kidney Disease, Chronic Obstructive Pulmonary Disease, Coronary Heart Disease, Dementia, Depression, Diabetes Mellitus, Heart Failure 1, Heart Failure 3, Hypertension, Mental Health, Non-Diabetic Hyperglycaemia, Osteoporosis, Rheumatoid Arthritis, Stroke & TIA

Data sources:
PxStat (NI / LGD / HSCT levels):

DISPREVNI, DISPREVLGD, DISPREVHSCT matrices

Excel workbook (GP-practice level — not in PxStat):

https://www.health-ni.gov.uk/topics/health-statistics/disease-prevalence

Update Frequency:

Annual, approximately May of the following calendar year.

Example

>>> from bolster.data_sources.nisra import disease_prevalence as dp
>>> df = dp.get_latest_disease_prevalence()
>>> 'registered_patients' in df.columns
True
>>> 'prevalence_per_1000' in df.columns
True

Attributes

logger

Functions

get_ni_prevalence([force_refresh])

Get NI-wide annual disease prevalence (DISPREVNI).

get_lgd_prevalence([force_refresh])

Get annual disease prevalence by Local Government District (DISPREVLGD).

get_hsct_prevalence([force_refresh])

Get annual disease prevalence by HSC Trust (DISPREVHSCT).

get_latest_disease_prevalence([force_refresh, level, lcg])

Get the latest NI disease prevalence data.

validate_disease_prevalence(df[, level])

Validate the disease prevalence DataFrame for internal consistency.

get_latest_publication_url()

Return the URL of the most recent disease prevalence Excel workbook.

parse_gp_practice_lookup(file_path[, sheet_name])

Parse Table 4 (GP practice details) into a lookup DataFrame.

parse_all_gp_practices(file_path)

Parse all Table 5 sheets and return a concatenated long-format DataFrame.

get_latest_gp_prevalence([force_refresh])

Fetch and return the latest GP-practice-level disease prevalence data.

Module Contents

bolster.data_sources.health_ni.disease_prevalence.logger[source]
bolster.data_sources.health_ni.disease_prevalence.get_ni_prevalence(force_refresh=False)[source]

Get NI-wide annual disease prevalence (DISPREVNI).

Parameters:

force_refresh (bool) – Accepted for API compatibility but ignored; the PxStat API always returns the latest data without caching.

Returns:

financial_year, year, disease, registered_patients, prevalence_per_1000.

Return type:

DataFrame with columns

bolster.data_sources.health_ni.disease_prevalence.get_lgd_prevalence(force_refresh=False)[source]

Get annual disease prevalence by Local Government District (DISPREVLGD).

Parameters:

force_refresh (bool) – Accepted for API compatibility but ignored; the PxStat API always returns the latest data without caching.

Returns:

financial_year, year, lgd, disease, registered_patients, prevalence_per_1000.

Return type:

DataFrame with columns

bolster.data_sources.health_ni.disease_prevalence.get_hsct_prevalence(force_refresh=False)[source]

Get annual disease prevalence by HSC Trust (DISPREVHSCT).

Parameters:

force_refresh (bool) – Accepted for API compatibility but ignored; the PxStat API always returns the latest data without caching.

Returns:

financial_year, year, trust, disease, registered_patients, prevalence_per_1000.

Return type:

DataFrame with columns

bolster.data_sources.health_ni.disease_prevalence.get_latest_disease_prevalence(force_refresh=False, level='ni', lcg=None)[source]

Get the latest NI disease prevalence data.

Fetches data from the NISRA PxStat API. The level parameter controls geographic granularity; lcg filters to a specific Local Government District (when level=’lgd’).

Parameters:
  • force_refresh (bool) – Accepted for API compatibility but ignored; the PxStat API always returns the latest data without caching.

  • level (str) – Geographic level — ‘ni’ for NI-wide (default), ‘lgd’ for Local Government District breakdown, ‘trust’ for HSC Trust, or ‘gp’ for GP-practice-level data (sourced from Excel, not PxStat).

  • lcg (str | None) – Optional LGD name filter (used when level=’lgd’). If provided, only rows for that LGD are returned.

Returns:

financial_year, year, disease, registered_patients, prevalence_per_1000. When level=’lgd’, also includes an ‘lgd’ column. When level=’trust’, also includes a ‘trust’ column.

Return type:

DataFrame with columns

Raises:

ValueError – If level is not one of ‘ni’, ‘lgd’, or ‘trust’.

Example

>>> df = get_latest_disease_prevalence()
>>> 'registered_patients' in df.columns
True
>>> 'prevalence_per_1000' in df.columns
True
bolster.data_sources.health_ni.disease_prevalence.validate_disease_prevalence(df, level='ni')[source]

Validate the disease prevalence DataFrame for internal consistency.

Parameters:
  • df (pandas.DataFrame) – DataFrame as returned by get_latest_disease_prevalence().

  • level (str) – Validation mode — ‘ni’ (default) or ‘lgd’/’trust’ for geographic breakdowns. Validates the ‘gp’ level alias for backward compatibility (treated same as ‘lgd’).

Returns:

True if all checks pass.

Raises:
Return type:

bool

Example

>>> import pandas as pd
>>> df = pd.DataFrame({
...     "year": [2017], "financial_year": ["2017/18"],
...     "disease": ["Hypertension"],
...     "registered_patients": [184824.0],
...     "prevalence_per_1000": [102.9],
... })
>>> validate_disease_prevalence(df)
True
bolster.data_sources.health_ni.disease_prevalence.get_latest_publication_url()[source]

Return the URL of the most recent disease prevalence Excel workbook.

Returns:

Absolute URL of the latest Excel workbook.

Raises:

NISRADataNotFoundError – If the Excel link cannot be located.

Return type:

str

Example

>>> url = get_latest_publication_url()
>>> url.endswith(".xlsx")
True
bolster.data_sources.health_ni.disease_prevalence.parse_gp_practice_lookup(file_path, sheet_name=None)[source]

Parse Table 4 (GP practice details) into a lookup DataFrame.

Parameters:
  • file_path (str) – Path to the downloaded .xlsx workbook.

  • sheet_name (str | None) – Sheet name override; defaults to "Table 4 GP practice details".

Returns:

practice_code, practice_name, address, postcode.

Return type:

DataFrame with columns

Raises:

NISRADataNotFoundError – If the sheet cannot be found.

Example

>>> lkp = parse_gp_practice_lookup("/tmp/rdptd-tables-2026.xlsx")
>>> "practice_code" in lkp.columns
True
>>> lkp["practice_code"].str.startswith("Z").all()
True
bolster.data_sources.health_ni.disease_prevalence.parse_all_gp_practices(file_path)[source]

Parse all Table 5 sheets and return a concatenated long-format DataFrame.

Parameters:

file_path (str) – Path to the downloaded .xlsx workbook.

Returns:

practice_code, practice_name, lcg, federation, financial_year, year, register, registered_patients, prevalence_per_1000.

Return type:

Long-format DataFrame with columns

Raises:

NISRADataNotFoundError – If no Table 5 sheets can be found or parsed.

Example

>>> df = parse_all_gp_practices("/tmp/rdptd-tables-2026.xlsx")
>>> df["financial_year"].nunique() >= 17
True
>>> df["practice_code"].nunique() >= 300
True
bolster.data_sources.health_ni.disease_prevalence.get_latest_gp_prevalence(force_refresh=False)[source]

Fetch and return the latest GP-practice-level disease prevalence data.

Downloads the current Excel workbook from the Department of Health website (cached for one year), parses all Table 5 sheets, and returns a clean long-format DataFrame covering 2009/10 to the latest published year.

Parameters:

force_refresh (bool) – If True, bypass the local file cache and re-download.

Returns:

  • practice_code (str): GP practice identifier (e.g. "Z00001")

  • practice_name (str or None): Practice name from Table 4

  • lcg (str or None): Local Commissioning Group

  • federation (str or None): Federation name (None pre-2017/18)

  • financial_year (str): e.g. "2025/26"

  • year (int): Start year of the financial year

  • register (str): Disease register name (normalised)

  • registered_patients (float): Patients on register at NPD

  • prevalence_per_1000 (float): Prevalence per 1,000 registered pts

Return type:

Long-format DataFrame with columns

Raises:
  • NISRADataNotFoundError – If the workbook cannot be located or downloaded.

  • NISRAValidationError – If the parsed data fails validation.

Example

>>> df = get_latest_gp_prevalence()
>>> df["practice_code"].str.startswith("Z").all()
True
>>> df["financial_year"].nunique() >= 3
True