bolster.data_sources.nisra.index_of_production ============================================== .. py:module:: bolster.data_sources.nisra.index_of_production .. autoapi-nested-parse:: NISRA Index of Production (IOP) for Northern Ireland. Provides quarterly index of manufacturing and production output, comparing Northern Ireland against the UK average. Base year 2020=100. Sectors covered (with approximate weights): - Manufacturing (78.8%): food, drink, tobacco, textiles, chemicals, machinery, etc. - Electricity, gas, steam (11.0%) - Water supply and waste management (8.4%) - Mining and quarrying (1.8%) Data Source: **Statistics page**: https://www.nisra.gov.uk/statistics/economic-output/index-production The module scrapes this page to find the latest quarterly publication, then downloads the Excel tables file. Update Frequency: Quarterly (published ~3 months after reference quarter) Geographic Coverage: Northern Ireland and UK comparison Base Year: 2020=100 .. rubric:: Example >>> from bolster.data_sources.nisra import index_of_production as iop >>> df = iop.get_latest_iop() >>> 'ni_index' in df.columns True Attributes ---------- .. autoapisummary:: bolster.data_sources.nisra.index_of_production.logger bolster.data_sources.nisra.index_of_production.IOP_STATS_URL bolster.data_sources.nisra.index_of_production.IOP_BASE_URL Functions --------- .. autoapisummary:: bolster.data_sources.nisra.index_of_production.get_latest_iop_publication_url bolster.data_sources.nisra.index_of_production.parse_iop_file bolster.data_sources.nisra.index_of_production.get_latest_iop bolster.data_sources.nisra.index_of_production.validate_iop_data bolster.data_sources.nisra.index_of_production.get_iop_by_year bolster.data_sources.nisra.index_of_production.get_iop_by_quarter bolster.data_sources.nisra.index_of_production.get_iop_summary_statistics bolster.data_sources.nisra.index_of_production.get_iop_growth Module Contents --------------- .. py:data:: logger .. py:data:: IOP_STATS_URL :value: 'https://www.nisra.gov.uk/statistics/economic-output/index-production' .. py:data:: IOP_BASE_URL :value: 'https://www.nisra.gov.uk' .. py:function:: get_latest_iop_publication_url() Scrape the IOP statistics page to find the latest quarterly Excel file. :returns: Tuple of (excel_url, year, quarter) :raises NISRADataNotFoundError: If publication cannot be found .. py:function:: parse_iop_file(file_path) Parse IOP Excel tables file into long-format DataFrame. Reads Table_1 which contains the headline NI and UK index series. :param file_path: Path to downloaded IOP tables Excel file :returns: - date: Timestamp (first day of quarter) - year: int - quarter: int (1-4) - quarter_label: str (e.g. "Q1 2025") - ni_index: float (NI Index of Production, 2020=100) - uk_index: float (UK Index of Production, 2020=100) :rtype: DataFrame with columns :raises NISRAValidationError: If file structure is unexpected .. py:function:: get_latest_iop(force_refresh = False) Get the latest NI Index of Production quarterly series. :param force_refresh: If True, bypass cache and download fresh data :returns: date, year, quarter, quarter_label, ni_index, uk_index (base year 2020=100) :rtype: DataFrame with columns :raises NISRADataNotFoundError: If latest publication cannot be found :raises NISRAValidationError: If file structure is unexpected .. rubric:: Example >>> df = get_latest_iop() >>> 'ni_index' in df.columns True .. py:function:: validate_iop_data(df) Validate IOP DataFrame for basic integrity. :param df: DataFrame from get_latest_iop() :returns: True if validation passes :raises NISRAValidationError: If validation fails .. py:function:: get_iop_by_year(df, year) Filter IOP data to a specific year. :param df: DataFrame from get_latest_iop() :param year: Year to filter :returns: Filtered DataFrame (up to 4 quarters) .. rubric:: Example >>> df = get_latest_iop() >>> df_2024 = get_iop_by_year(df, 2024) >>> len(df_2024) <= 4 True .. py:function:: get_iop_by_quarter(df, quarter, year) Filter IOP data to a specific quarter. :param df: DataFrame from get_latest_iop() :param quarter: Quarter number (1-4) :param year: Year :returns: Filtered DataFrame (single row) .. rubric:: Example >>> df = get_latest_iop() >>> q1_2024 = get_iop_by_quarter(df, 1, 2024) >>> len(q1_2024) == 1 True .. py:function:: get_iop_summary_statistics(df, start_year = None, end_year = None) Calculate summary statistics for a period of IOP data. :param df: DataFrame from get_latest_iop() :param start_year: Optional start year filter (inclusive) :param end_year: Optional end year filter (inclusive) :returns: period, ni_mean, ni_min, ni_max, uk_mean, uk_min, uk_max, quarters_count :rtype: Dictionary with keys .. rubric:: Example >>> df = get_latest_iop() >>> stats = get_iop_summary_statistics(df, start_year=2020) >>> 'ni_mean' in stats True .. py:function:: get_iop_growth(df) Calculate quarter-on-quarter and year-on-year growth rates. :param df: DataFrame from get_latest_iop() :returns: - ni_qoq: NI quarter-on-quarter % change - ni_yoy: NI year-on-year % change - uk_qoq: UK quarter-on-quarter % change - uk_yoy: UK year-on-year % change :rtype: DataFrame with additional columns .. rubric:: Example >>> df = get_latest_iop() >>> growth = get_iop_growth(df) >>> 'ni_yoy' in growth.columns True