bolster.data_sources.health_ni.disease_prevalence ================================================= .. py:module:: bolster.data_sources.health_ni.disease_prevalence .. autoapi-nested-parse:: 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. .. rubric:: 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 ---------- .. autoapisummary:: bolster.data_sources.health_ni.disease_prevalence.logger Functions --------- .. autoapisummary:: bolster.data_sources.health_ni.disease_prevalence.get_ni_prevalence bolster.data_sources.health_ni.disease_prevalence.get_lgd_prevalence bolster.data_sources.health_ni.disease_prevalence.get_hsct_prevalence bolster.data_sources.health_ni.disease_prevalence.get_latest_disease_prevalence bolster.data_sources.health_ni.disease_prevalence.validate_disease_prevalence bolster.data_sources.health_ni.disease_prevalence.get_latest_publication_url bolster.data_sources.health_ni.disease_prevalence.parse_gp_practice_lookup bolster.data_sources.health_ni.disease_prevalence.parse_all_gp_practices bolster.data_sources.health_ni.disease_prevalence.get_latest_gp_prevalence Module Contents --------------- .. py:data:: logger .. py:function:: get_ni_prevalence(force_refresh = False) Get NI-wide annual disease prevalence (DISPREVNI). :param force_refresh: 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. :rtype: DataFrame with columns .. py:function:: get_lgd_prevalence(force_refresh = False) Get annual disease prevalence by Local Government District (DISPREVLGD). :param force_refresh: 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. :rtype: DataFrame with columns .. py:function:: get_hsct_prevalence(force_refresh = False) Get annual disease prevalence by HSC Trust (DISPREVHSCT). :param force_refresh: 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. :rtype: DataFrame with columns .. py:function:: get_latest_disease_prevalence(force_refresh = False, level = 'ni', lcg = None) 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'). :param force_refresh: Accepted for API compatibility but ignored; the PxStat API always returns the latest data without caching. :param level: 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). :param lcg: 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. :rtype: DataFrame with columns :raises ValueError: If level is not one of 'ni', 'lgd', or 'trust'. .. rubric:: Example >>> df = get_latest_disease_prevalence() >>> 'registered_patients' in df.columns True >>> 'prevalence_per_1000' in df.columns True .. py:function:: validate_disease_prevalence(df, level = 'ni') Validate the disease prevalence DataFrame for internal consistency. :param df: DataFrame as returned by :func:`get_latest_disease_prevalence`. :param level: 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 NISRAValidationError: Describing the first failing check. :raises ValueError: If level is not a recognised value. .. rubric:: 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 .. py:function:: get_latest_publication_url() 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. .. rubric:: Example >>> url = get_latest_publication_url() >>> url.endswith(".xlsx") True .. py:function:: parse_gp_practice_lookup(file_path, sheet_name = None) Parse Table 4 (GP practice details) into a lookup DataFrame. :param file_path: Path to the downloaded .xlsx workbook. :param sheet_name: Sheet name override; defaults to ``"Table 4 GP practice details"``. :returns: practice_code, practice_name, address, postcode. :rtype: DataFrame with columns :raises NISRADataNotFoundError: If the sheet cannot be found. .. rubric:: 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 .. py:function:: parse_all_gp_practices(file_path) Parse all Table 5 sheets and return a concatenated long-format DataFrame. :param file_path: Path to the downloaded .xlsx workbook. :returns: practice_code, practice_name, lcg, federation, financial_year, year, register, registered_patients, prevalence_per_1000. :rtype: Long-format DataFrame with columns :raises NISRADataNotFoundError: If no Table 5 sheets can be found or parsed. .. rubric:: Example >>> df = parse_all_gp_practices("/tmp/rdptd-tables-2026.xlsx") >>> df["financial_year"].nunique() >= 17 True >>> df["practice_code"].nunique() >= 300 True .. py:function:: get_latest_gp_prevalence(force_refresh = False) 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. :param force_refresh: 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 :rtype: Long-format DataFrame with columns :raises NISRADataNotFoundError: If the workbook cannot be located or downloaded. :raises NISRAValidationError: If the parsed data fails validation. .. rubric:: Example >>> df = get_latest_gp_prevalence() >>> df["practice_code"].str.startswith("Z").all() True >>> df["financial_year"].nunique() >= 3 True