{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "ad2bb8088747dade",
   "metadata": {},
   "source": [
    "# Analiza i prognozowanie inflacji w województwach Polski\n",
    "\n",
    "## 1. Opis problemu\n",
    "\n",
    "Inflacja, rozumiana jako wzrost ogólnego poziomu cen towarów i usług w gospodarce, to jeden z najważniejszych wskaźników makroekonomicznych. Ma ona bezpośredni wpływ na siłę nabywczą ludności, stabilność gospodarczą oraz decyzje inwestycyjne. Monitorowanie i prognozowanie inflacji na poziomie województw pozwala zrozumieć zróżnicowanie procesów gospodarczych w różnych regionach Polski, a także wspiera podejmowanie trafnych decyzji przez samorządy, przedsiębiorców oraz mieszkańców. Prognozy inflacji są wykorzystywane m.in. w planowaniu budżetów, indeksacji wynagrodzeń i świadczeń, a także w ocenie ryzyka inwestycyjnego. Aktualność i praktyczne znaczenie tego zagadnienia sprawiają, że analiza regionalnych wskaźników inflacji stanowi wartościowy przedmiot badań.\n",
    "\n",
    "### Wyjaśnienie sposobu pomiaru inflacji w Banku Danych Lokalnych\n",
    "\n",
    "Wskaźniki inflacji wykorzystane w niniejszej analizie pochodzą z Banku Danych Lokalnych GUS i zostały opracowane na podstawie przeciętnych cen producentów na rynku krajowym. Ceny skupu obejmują przeciętne roczne ceny płacone przez podmioty gospodarcze skupujące produkty rolne bezpośrednio od producentów rolnych. Podstawą do opracowania wskaźników cen towarów i usług są obserwacje cen reprezentantów, a prezentowane dane mają charakter szacunkowy.\n",
    "\n",
    "## 2. Opis sposobu rozwiązania\n",
    "\n",
    "W analizie wykorzystano kwartalne dane o wskaźnikach inflacji w poszczególnych województwach Polski z lat 2005–2024. Zbiór danych umożliwia analizę przestrzenno-czasową oraz przygotowanie prognoz na kolejne okresy. Zakres danych pozwala zidentyfikować trendy, sezonowość i anomalie w kształtowaniu się inflacji regionalnej.\n",
    "\n",
    "Dane zostały poddane oczyszczeniu oraz transformacjom przygotowującym je do analizy szeregów czasowych. Eksploracyjna analiza danych objęła statystyki opisowe, analizę rozkładów, wykrywanie wartości odstających oraz identyfikację sezonowości. Do prognozowania kwartalnych wskaźników inflacji dla każdego województwa zastosowano model ARIMA, którego parametry zostały dobrane automatycznie na podstawie szeregów czasowych. Podział na zbiór treningowy (do 2022 roku) oraz testowy (2023–2024) pozwolił na ocenę jakości prognoz.\n",
    "\n",
    "Wyniki zostały przedstawione w formie tabelarycznej oraz wizualnej (wykresy, mapa Polski), co umożliwia intuicyjne porównanie sytuacji w regionach oraz ocenę precyzji prognoz."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "77f3f16c9d4fda0f",
   "metadata": {},
   "source": [
    "## 3. Kod zawierający obliczenia\n",
    "\n",
    "Poniżej przedstawiono fragmenty kodu realizujące kolejne etapy analizy. Po każdym bloku kodu zamieszczono odpowiadające mu wykresy oraz – w przypadku analizy wartości odstających – opis procesu myślowego dotyczącego ich interpretacji i decyzji analitycznych.\n",
    "\n",
    "---\n",
    "\n",
    "### Wczytanie i przygotowanie danych"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "753f199cb80ee6b2",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-17T13:35:06.907187Z",
     "start_time": "2025-06-17T13:35:06.151259Z"
    }
   },
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "import geopandas as gpd\n",
    "from statsmodels.tsa.arima.model import ARIMA\n",
    "from pmdarima import auto_arima\n",
    "from sklearn.metrics import mean_absolute_error"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "ec16213f0dde4741",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-17T13:35:07.003382Z",
     "start_time": "2025-06-17T13:35:06.985887Z"
    }
   },
   "outputs": [],
   "source": [
    "# Ścieżka do pliku z danymi\n",
    "data_path = \"raw_data.csv\"\n",
    "\n",
    "# Wczytanie i wstępna obróbka danych\n",
    "df = pd.read_csv(data_path, sep=';', encoding='utf-8', low_memory=False)\n",
    "\n",
    "df.dropna(axis=1, how='all', inplace=True)\n",
    "df.drop(columns=['Atrybut', 'Jednostka miary', 'Kod', 'Wskaźnik cen'], inplace=True, errors='ignore')\n",
    "df = df[df['Rok'] != 2025]\n",
    "\n",
    "df.rename(columns={'Nazwa': 'Wojewodztwo', 'Okresy': 'Okres'}, inplace=True)\n",
    "df.sort_values(by=[\"Wojewodztwo\", 'Rok', 'Okres'], inplace=True)\n",
    "df.reset_index(drop=True, inplace=True)\n",
    "\n",
    "df['Rok'] = df['Rok'].astype(int)\n",
    "\n",
    "okres_mapping = {'1 kwartał': 'Q1', '2 kwartał': 'Q2', '3 kwartał': 'Q3', '4 kwartał': 'Q4'}\n",
    "df['Okres'] = df['Okres'].map(okres_mapping)\n",
    "df['Okres'] = pd.Categorical(df['Okres'], categories=['Q1', 'Q2', 'Q3', 'Q4'], ordered=True)\n",
    "\n",
    "df['Wartosc'] = pd.to_numeric(df['Wartosc'].str.replace(',', '.'), errors='coerce')\n",
    "\n",
    "df['Okres_czas'] = df['Rok'].astype(str) + df['Okres'].str.replace('Q', '-Q')\n",
    "df['Okres_czas'] = pd.PeriodIndex(df['Okres_czas'], freq='Q')\n",
    "\n",
    "df = df.sort_values(['Wojewodztwo', 'Okres_czas']).reset_index(drop=True)\n",
    "\n",
    "df['Kwartal'] = df['Rok'].astype(str) + '-' + df['Okres'].astype(str)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f1cb55b875daac5f",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "### Eksploracyjna analiza danych"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "cd2fde93287b4597",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-17T13:35:07.026609Z",
     "start_time": "2025-06-17T13:35:07.015850Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 1280 entries, 0 to 1279\n",
      "Data columns (total 6 columns):\n",
      " #   Column       Non-Null Count  Dtype        \n",
      "---  ------       --------------  -----        \n",
      " 0   Wojewodztwo  1280 non-null   object       \n",
      " 1   Okres        1280 non-null   category     \n",
      " 2   Rok          1280 non-null   int64        \n",
      " 3   Wartosc      1280 non-null   float64      \n",
      " 4   Okres_czas   1280 non-null   period[Q-DEC]\n",
      " 5   Kwartal      1280 non-null   object       \n",
      "dtypes: category(1), float64(1), int64(1), object(2), period[Q-DEC](1)\n",
      "memory usage: 51.6+ KB\n",
      "None\n",
      "\n",
      "Zakres lat: 2005 - 2024\n",
      "Województwa: ['DOLNOŚLĄSKIE' 'KUJAWSKO-POMORSKIE' 'LUBELSKIE' 'LUBUSKIE' 'MAZOWIECKIE'\n",
      " 'MAŁOPOLSKIE' 'OPOLSKIE' 'PODKARPACKIE' 'PODLASKIE' 'POMORSKIE'\n",
      " 'WARMIŃSKO-MAZURSKIE' 'WIELKOPOLSKIE' 'ZACHODNIOPOMORSKIE' 'ŁÓDZKIE'\n",
      " 'ŚLĄSKIE' 'ŚWIĘTOKRZYSKIE']\n",
      "\n",
      "Statystyki opisowe dla inflacji:\n",
      "count    1280.000000\n",
      "mean      100.835703\n",
      "std         1.169597\n",
      "min        99.000000\n",
      "25%       100.100000\n",
      "50%       100.500000\n",
      "75%       101.400000\n",
      "max       107.000000\n",
      "Name: Wartosc, dtype: float64\n",
      "\n",
      "Statystyki opisowe dla inflacji (grupowane według województw):\n",
      "                          mean       std   min    max\n",
      "Wojewodztwo                                          \n",
      "DOLNOŚLĄSKIE         100.82375  1.116986  99.3  105.5\n",
      "KUJAWSKO-POMORSKIE   100.85125  1.221432  99.3  106.6\n",
      "LUBELSKIE            100.78125  1.177757  99.1  106.3\n",
      "LUBUSKIE             100.87875  1.145127  99.4  105.5\n",
      "MAZOWIECKIE          100.80750  1.101986  99.3  105.3\n",
      "MAŁOPOLSKIE          100.89750  1.219356  99.4  105.6\n",
      "OPOLSKIE             100.83625  1.188366  99.2  105.9\n",
      "PODKARPACKIE         100.85125  1.155942  99.0  104.9\n",
      "PODLASKIE            100.79000  1.177704  99.3  106.7\n",
      "POMORSKIE            100.80250  1.106022  99.4  105.4\n",
      "WARMIŃSKO-MAZURSKIE  100.82875  1.182059  99.1  105.9\n",
      "WIELKOPOLSKIE        100.88125  1.208000  99.1  106.3\n",
      "ZACHODNIOPOMORSKIE   100.83125  1.152608  99.5  105.4\n",
      "ŁÓDZKIE              100.85250  1.214154  99.3  106.3\n",
      "ŚLĄSKIE              100.79875  1.157966  99.3  105.5\n",
      "ŚWIĘTOKRZYSKIE       100.85875  1.277229  99.1  107.0\n"
     ]
    }
   ],
   "source": [
    "# Informacje o danych\n",
    "print(df.info())\n",
    "\n",
    "# Zakres lat i unikalne jednostki\n",
    "print(\"\\nZakres lat:\", df['Rok'].min(), '-', df['Rok'].max())\n",
    "print(\"Województwa:\", df['Wojewodztwo'].unique())\n",
    "\n",
    "# Statystyki opisowe dla inflacji\n",
    "print(\"\\nStatystyki opisowe dla inflacji:\")\n",
    "print(df['Wartosc'].describe())\n",
    "\n",
    "print(\"\\nStatystyki opisowe dla inflacji (grupowane według województw):\")\n",
    "print(df.groupby('Wojewodztwo')['Wartosc'].agg(['mean', 'std', 'min', 'max']))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e7de3e4c",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "#### Wykres: Inflacja w wybranym województwie w czasie"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "f199dc0987fa3525",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-17T13:35:07.397775Z",
     "start_time": "2025-06-17T13:35:07.036629Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 94192 characters]",
      "text/plain": [
       "<Figure size 1600x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Wykres: Inflacja w czasie dla wybranego województwa\n",
    "woj = 'WIELKOPOLSKIE'\n",
    "fig, ax = plt.subplots(figsize=(16, 6))\n",
    "ax.plot(df[df['Wojewodztwo'] == woj]['Kwartal'], df[df['Wojewodztwo'] == woj]['Wartosc'], marker='o')\n",
    "ax.set_title(f'Inflacja w {woj} w czasie')\n",
    "ax.set_xlabel('Kwartał')\n",
    "ax.set_ylabel('Wartość')\n",
    "xticks = ax.get_xticks()\n",
    "ax.set_xticks(xticks[::2])\n",
    "plt.setp(ax.get_xticklabels(), rotation=90)\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "af383e30",
   "metadata": {},
   "source": [
    "*Wizualizacja: Inflacja w województwie wielkopolskim w czasie.*\n",
    "\n",
    "---\n",
    "\n",
    "#### Wykres: Porównanie rozkładów inflacji w województwach (boxplot)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "44ce4485daa13299",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-17T13:35:07.549428Z",
     "start_time": "2025-06-17T13:35:07.428099Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 69600 characters]",
      "text/plain": [
       "<Figure size 1600x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Wykres: Porównanie rozkładów inflacji w województwach (boxplot)\n",
    "plt.figure(figsize=(16,6))\n",
    "sns.boxplot(data=df, x='Wojewodztwo', y='Wartosc')\n",
    "plt.title('Rozkład inflacji w województwach')\n",
    "plt.xlabel('Województwo')\n",
    "plt.ylabel('Wartość')\n",
    "plt.xticks(rotation=90)\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ec8c48e3",
   "metadata": {},
   "source": [
    "*Wizualizacja: Porównanie rozkładów inflacji w regionach – wartości odstające są zbliżone w większości województw.*\n",
    "\n",
    "---\n",
    "\n",
    "#### Identyfikacja i analiza wartości odstających\n",
    "\n",
    "W procesie eksploracji danych pojawił się problem wartości odstających (outlierów). Wartości te mogą istotnie wpływać na wyniki modelowania szeregów czasowych, zwłaszcza w kontekście prognozowania. Przeprowadzono więc identyfikację wartości odstających dla każdego województwa osobno, korzystając z klasycznej reguły pudełkowej (1.5 x IQR).\n",
    "\n",
    "**Proces myślowy:**\n",
    "- Wartości odstające zostały potraktowane nie jako anomalia danych, lecz jako potencjalny efekt rzeczywistych, gwałtownych zmian cen wywołanych przez zjawiska o charakterze ogólnokrajowym (np. pandemia COVID-19).\n",
    "- Zdecydowano się nie usuwać outlierów, ponieważ ich obecność odzwierciedla pełną dynamikę inflacji i pozwala modelowi ARIMA lepiej uchwycić ryzyko powtórzenia się podobnych sytuacji w przyszłości.\n",
    "- Obserwacje odstające występowały w tym samym okresie we wszystkich województwach, co sugeruje, że nie były wynikiem błędów pomiarowych czy specyfiki regionalnej, lecz ogólnopolskich szoków gospodarczych."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "4d72e0d18900a279",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-17T13:59:59.048634Z",
     "start_time": "2025-06-17T13:59:57.644750Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 468040 characters]",
      "text/plain": [
       "<Figure size 2500x1200 with 16 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import warnings\n",
    "\n",
    "def find_outliers(group):\n",
    "    q1 = group['Wartosc'].quantile(0.25)\n",
    "    q3 = group['Wartosc'].quantile(0.75)\n",
    "    iqr = q3 - q1\n",
    "    lower = q1 - 1.5 * iqr\n",
    "    upper = q3 + 1.5 * iqr\n",
    "    outliers = group[(group['Wartosc'] < lower) | (group['Wartosc'] > upper)]\n",
    "    return outliers\n",
    "\n",
    "with warnings.catch_warnings():\n",
    "    warnings.simplefilter('ignore')\n",
    "    outliers_df = df.groupby('Wojewodztwo', group_keys=False).apply(find_outliers).reset_index()\n",
    "\n",
    "wojewodztwa = df['Wojewodztwo'].unique()\n",
    "n = len(wojewodztwa)\n",
    "cols = 4\n",
    "rows = (n + cols - 1) // cols\n",
    "\n",
    "fig, axes = plt.subplots(rows, cols, figsize=(25, 12), sharex=False)\n",
    "axes = axes.flatten()\n",
    "\n",
    "for i, woj in enumerate(wojewodztwa):\n",
    "    woj_df = df[df['Wojewodztwo'] == woj]\n",
    "    woj_out = outliers_df[outliers_df['Wojewodztwo'] == woj]\n",
    "    ax = axes[i]\n",
    "    ax.plot(woj_df['Kwartal'], woj_df['Wartosc'], marker='o', label='Wartości')\n",
    "    ax.scatter(woj_out['Kwartal'], woj_out['Wartosc'], color='red', label='Outliery', zorder=5)\n",
    "    ax.set_title(woj)\n",
    "    ax.set_xlabel('Kwartal')\n",
    "    ax.set_ylabel('Wartosc')\n",
    "    xticks = ax.get_xticks()\n",
    "    ax.set_xticks(xticks[::4])\n",
    "    ax.tick_params(axis='x', rotation=90)\n",
    "    ax.legend(fontsize=8)\n",
    "\n",
    "# Ukryj puste osie\n",
    "for j in range(i+1, len(axes)):\n",
    "    axes[j].set_visible(False)\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d454c06d",
   "metadata": {},
   "source": [
    "*Wizualizacja: Wartości odstające inflacji w poszczególnych województwach.*\n",
    "\n",
    "---\n",
    "\n",
    "#### Wykres: Średnia inflacja w poszczególnych kwartałach"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "7db388b5abaf91e7",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-17T13:35:07.955089Z",
     "start_time": "2025-06-17T13:35:07.865300Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 30148 characters]",
      "text/plain": [
       "<Figure size 1000x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Wykres: Średnia inflacja wg kwartału\n",
    "plt.figure(figsize=(10,5))\n",
    "sns.barplot(data=df, x='Okres', y='Wartosc')\n",
    "plt.title('Średnia inflacja w poszczególnych kwartałach')\n",
    "plt.ylim(90, None)\n",
    "plt.xlabel('Kwartal')\n",
    "plt.ylabel('Średnia wartość inflacji')\n",
    "plt.tight_layout()\n",
    "for p in plt.gca().patches:\n",
    "    plt.gca().annotate(f'{p.get_height():.2f}', (p.get_x() + p.get_width() / 2., p.get_height()),\n",
    "                       ha='center', va='bottom', fontsize=10, color='black', rotation=0)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f088cff162cbda65",
   "metadata": {},
   "source": [
    "*Wizualizacja: Sezonowość inflacji – najwyższe wartości na początku roku.*\n",
    "\n",
    "---\n",
    "\n",
    "### Prognozowanie inflacji"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "48f329a5e5283925",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-17T13:35:38.213401Z",
     "start_time": "2025-06-17T13:35:07.990786Z"
    }
   },
   "outputs": [
    {
     "data": {
      "application/vnd.microsoft.datawrangler.viewer.v0+json": {
       "columns": [
        {
         "name": "index",
         "rawType": "int64",
         "type": "integer"
        },
        {
         "name": "Wojewodztwo",
         "rawType": "object",
         "type": "string"
        },
        {
         "name": "MAE",
         "rawType": "float64",
         "type": "float"
        },
        {
         "name": "RMSE",
         "rawType": "float64",
         "type": "float"
        },
        {
         "name": "Prognoza_nast_Q1",
         "rawType": "float64",
         "type": "float"
        },
        {
         "name": "Prognoza_nast_Q2",
         "rawType": "float64",
         "type": "float"
        },
        {
         "name": "Prognoza_nast_Q3",
         "rawType": "float64",
         "type": "float"
        },
        {
         "name": "Prognoza_nast_Q4",
         "rawType": "float64",
         "type": "float"
        }
       ],
       "ref": "f418d76e-9b37-4671-be04-fcc536c804ba",
       "rows": [
        [
         "0",
         "DOLNOŚLĄSKIE",
         "1.0579904775083104",
         "1.3499980573763053",
         "103.04260396034785",
         "103.75783990941811",
         "102.22818141051873",
         "101.5048721061602"
        ],
        [
         "1",
         "KUJAWSKO-POMORSKIE",
         "1.79821579993639",
         "2.10985756274283",
         "104.25779548190691",
         "105.05667369433826",
         "103.66746756488358",
         "102.56556801801891"
        ],
        [
         "2",
         "LUBELSKIE",
         "1.8426115305490995",
         "2.201423495500652",
         "104.02826654403735",
         "104.91052181131066",
         "103.16943706940845",
         "103.04137909952047"
        ],
        [
         "3",
         "LUBUSKIE",
         "2.63026195755781",
         "2.8358313113396965",
         "105.12503313545265",
         "105.43895780265655",
         "103.76161028563737",
         "103.90974393914821"
        ],
        [
         "4",
         "MAZOWIECKIE",
         "2.2109089912127633",
         "2.382601291405757",
         "104.22237190002637",
         "104.95971975667952",
         "102.87552234895496",
         "103.41201273656895"
        ],
        [
         "5",
         "MAŁOPOLSKIE",
         "3.100145432094731",
         "3.327341233004455",
         "104.63935660938844",
         "105.28519564308313",
         "104.1730873699702",
         "104.19873148214671"
        ],
        [
         "6",
         "OPOLSKIE",
         "1.2731301382063975",
         "1.776169577530145",
         "103.26995028462159",
         "103.90233866717338",
         "103.21613154598505",
         "101.98485846487709"
        ],
        [
         "7",
         "PODKARPACKIE",
         "1.6620434602195786",
         "1.895028239209868",
         "103.98346116074723",
         "103.96588960415131",
         "103.15999140598909",
         "102.937567934533"
        ],
        [
         "8",
         "PODLASKIE",
         "1.833320884757537",
         "2.1309765078135974",
         "103.56481527045725",
         "104.85234345804533",
         "103.01606530508994",
         "102.9208224856891"
        ],
        [
         "9",
         "POMORSKIE",
         "2.744541393462587",
         "2.935635862820699",
         "104.55824147099659",
         "104.97613410186426",
         "103.59496983062454",
         "103.83309716350242"
        ],
        [
         "10",
         "WARMIŃSKO-MAZURSKIE",
         "2.2763609554283875",
         "2.5143402116806404",
         "104.12661075190552",
         "104.82013072443124",
         "103.33969694818622",
         "103.4884207366903"
        ],
        [
         "11",
         "WIELKOPOLSKIE",
         "1.977402254860154",
         "2.313829544641495",
         "104.17499276373779",
         "105.09240261225966",
         "103.63122198924682",
         "103.08180562768334"
        ],
        [
         "12",
         "ZACHODNIOPOMORSKIE",
         "2.142560169210684",
         "2.4860098670401367",
         "105.09254901995106",
         "104.98564433955536",
         "103.63400141815598",
         "103.86986950316651"
        ],
        [
         "13",
         "ŁÓDZKIE",
         "2.6550854341218404",
         "2.8511564310304527",
         "104.21545503819937",
         "105.24303768056038",
         "103.61217270059532",
         "103.65036016724282"
        ],
        [
         "14",
         "ŚLĄSKIE",
         "1.665345629558466",
         "1.921836131793946",
         "103.71961003120798",
         "104.36223070264272",
         "103.0726170995497",
         "102.79263748638336"
        ],
        [
         "15",
         "ŚWIĘTOKRZYSKIE",
         "1.7688874643894756",
         "2.1515096483535032",
         "103.89808064196984",
         "104.89902953387376",
         "103.24999848032826",
         "102.58099106641444"
        ]
       ],
       "shape": {
        "columns": 7,
        "rows": 16
       }
      },
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Wojewodztwo</th>\n",
       "      <th>MAE</th>\n",
       "      <th>RMSE</th>\n",
       "      <th>Prognoza_nast_Q1</th>\n",
       "      <th>Prognoza_nast_Q2</th>\n",
       "      <th>Prognoza_nast_Q3</th>\n",
       "      <th>Prognoza_nast_Q4</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>DOLNOŚLĄSKIE</td>\n",
       "      <td>1.057990</td>\n",
       "      <td>1.349998</td>\n",
       "      <td>103.042604</td>\n",
       "      <td>103.757840</td>\n",
       "      <td>102.228181</td>\n",
       "      <td>101.504872</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>KUJAWSKO-POMORSKIE</td>\n",
       "      <td>1.798216</td>\n",
       "      <td>2.109858</td>\n",
       "      <td>104.257795</td>\n",
       "      <td>105.056674</td>\n",
       "      <td>103.667468</td>\n",
       "      <td>102.565568</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>LUBELSKIE</td>\n",
       "      <td>1.842612</td>\n",
       "      <td>2.201423</td>\n",
       "      <td>104.028267</td>\n",
       "      <td>104.910522</td>\n",
       "      <td>103.169437</td>\n",
       "      <td>103.041379</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>LUBUSKIE</td>\n",
       "      <td>2.630262</td>\n",
       "      <td>2.835831</td>\n",
       "      <td>105.125033</td>\n",
       "      <td>105.438958</td>\n",
       "      <td>103.761610</td>\n",
       "      <td>103.909744</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>MAZOWIECKIE</td>\n",
       "      <td>2.210909</td>\n",
       "      <td>2.382601</td>\n",
       "      <td>104.222372</td>\n",
       "      <td>104.959720</td>\n",
       "      <td>102.875522</td>\n",
       "      <td>103.412013</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>MAŁOPOLSKIE</td>\n",
       "      <td>3.100145</td>\n",
       "      <td>3.327341</td>\n",
       "      <td>104.639357</td>\n",
       "      <td>105.285196</td>\n",
       "      <td>104.173087</td>\n",
       "      <td>104.198731</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>OPOLSKIE</td>\n",
       "      <td>1.273130</td>\n",
       "      <td>1.776170</td>\n",
       "      <td>103.269950</td>\n",
       "      <td>103.902339</td>\n",
       "      <td>103.216132</td>\n",
       "      <td>101.984858</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>PODKARPACKIE</td>\n",
       "      <td>1.662043</td>\n",
       "      <td>1.895028</td>\n",
       "      <td>103.983461</td>\n",
       "      <td>103.965890</td>\n",
       "      <td>103.159991</td>\n",
       "      <td>102.937568</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>PODLASKIE</td>\n",
       "      <td>1.833321</td>\n",
       "      <td>2.130977</td>\n",
       "      <td>103.564815</td>\n",
       "      <td>104.852343</td>\n",
       "      <td>103.016065</td>\n",
       "      <td>102.920822</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>POMORSKIE</td>\n",
       "      <td>2.744541</td>\n",
       "      <td>2.935636</td>\n",
       "      <td>104.558241</td>\n",
       "      <td>104.976134</td>\n",
       "      <td>103.594970</td>\n",
       "      <td>103.833097</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>WARMIŃSKO-MAZURSKIE</td>\n",
       "      <td>2.276361</td>\n",
       "      <td>2.514340</td>\n",
       "      <td>104.126611</td>\n",
       "      <td>104.820131</td>\n",
       "      <td>103.339697</td>\n",
       "      <td>103.488421</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>WIELKOPOLSKIE</td>\n",
       "      <td>1.977402</td>\n",
       "      <td>2.313830</td>\n",
       "      <td>104.174993</td>\n",
       "      <td>105.092403</td>\n",
       "      <td>103.631222</td>\n",
       "      <td>103.081806</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>ZACHODNIOPOMORSKIE</td>\n",
       "      <td>2.142560</td>\n",
       "      <td>2.486010</td>\n",
       "      <td>105.092549</td>\n",
       "      <td>104.985644</td>\n",
       "      <td>103.634001</td>\n",
       "      <td>103.869870</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>ŁÓDZKIE</td>\n",
       "      <td>2.655085</td>\n",
       "      <td>2.851156</td>\n",
       "      <td>104.215455</td>\n",
       "      <td>105.243038</td>\n",
       "      <td>103.612173</td>\n",
       "      <td>103.650360</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>ŚLĄSKIE</td>\n",
       "      <td>1.665346</td>\n",
       "      <td>1.921836</td>\n",
       "      <td>103.719610</td>\n",
       "      <td>104.362231</td>\n",
       "      <td>103.072617</td>\n",
       "      <td>102.792637</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>ŚWIĘTOKRZYSKIE</td>\n",
       "      <td>1.768887</td>\n",
       "      <td>2.151510</td>\n",
       "      <td>103.898081</td>\n",
       "      <td>104.899030</td>\n",
       "      <td>103.249998</td>\n",
       "      <td>102.580991</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            Wojewodztwo       MAE      RMSE  Prognoza_nast_Q1  \\\n",
       "0          DOLNOŚLĄSKIE  1.057990  1.349998        103.042604   \n",
       "1    KUJAWSKO-POMORSKIE  1.798216  2.109858        104.257795   \n",
       "2             LUBELSKIE  1.842612  2.201423        104.028267   \n",
       "3              LUBUSKIE  2.630262  2.835831        105.125033   \n",
       "4           MAZOWIECKIE  2.210909  2.382601        104.222372   \n",
       "5           MAŁOPOLSKIE  3.100145  3.327341        104.639357   \n",
       "6              OPOLSKIE  1.273130  1.776170        103.269950   \n",
       "7          PODKARPACKIE  1.662043  1.895028        103.983461   \n",
       "8             PODLASKIE  1.833321  2.130977        103.564815   \n",
       "9             POMORSKIE  2.744541  2.935636        104.558241   \n",
       "10  WARMIŃSKO-MAZURSKIE  2.276361  2.514340        104.126611   \n",
       "11        WIELKOPOLSKIE  1.977402  2.313830        104.174993   \n",
       "12   ZACHODNIOPOMORSKIE  2.142560  2.486010        105.092549   \n",
       "13              ŁÓDZKIE  2.655085  2.851156        104.215455   \n",
       "14              ŚLĄSKIE  1.665346  1.921836        103.719610   \n",
       "15       ŚWIĘTOKRZYSKIE  1.768887  2.151510        103.898081   \n",
       "\n",
       "    Prognoza_nast_Q2  Prognoza_nast_Q3  Prognoza_nast_Q4  \n",
       "0         103.757840        102.228181        101.504872  \n",
       "1         105.056674        103.667468        102.565568  \n",
       "2         104.910522        103.169437        103.041379  \n",
       "3         105.438958        103.761610        103.909744  \n",
       "4         104.959720        102.875522        103.412013  \n",
       "5         105.285196        104.173087        104.198731  \n",
       "6         103.902339        103.216132        101.984858  \n",
       "7         103.965890        103.159991        102.937568  \n",
       "8         104.852343        103.016065        102.920822  \n",
       "9         104.976134        103.594970        103.833097  \n",
       "10        104.820131        103.339697        103.488421  \n",
       "11        105.092403        103.631222        103.081806  \n",
       "12        104.985644        103.634001        103.869870  \n",
       "13        105.243038        103.612173        103.650360  \n",
       "14        104.362231        103.072617        102.792637  \n",
       "15        104.899030        103.249998        102.580991  "
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import warnings\n",
    "\n",
    "wojewodztwa = df['Wojewodztwo'].unique()\n",
    "results = []\n",
    "\n",
    "for woj in wojewodztwa:\n",
    "    df_woj = df[df['Wojewodztwo'] == woj].sort_values('Okres_czas').set_index('Okres_czas')\n",
    "    train = df_woj[df_woj.index <= pd.Period('2022Q4')]\n",
    "    test = df_woj[df_woj.index >= pd.Period('2023Q1')]\n",
    "\n",
    "    # auto_arima\n",
    "    with warnings.catch_warnings():\n",
    "        warnings.simplefilter('ignore')\n",
    "        stepwise_model = auto_arima(train['Wartosc'], seasonal=True, m=4, suppress_warnings=True)\n",
    "    model = ARIMA(train['Wartosc'], order=stepwise_model.order, seasonal_order=stepwise_model.seasonal_order)\n",
    "    model_fit = model.fit(method_kwargs={\"maxiter\": 200})\n",
    "\n",
    "    # prognoza na okres testowy\n",
    "    forecast = model_fit.forecast(steps=len(test))\n",
    "    forecast.index = test.index\n",
    "\n",
    "    # błędy\n",
    "    mae = mean_absolute_error(test['Wartosc'], forecast)\n",
    "    rmse = np.sqrt(np.mean((test['Wartosc'] - forecast) ** 2))\n",
    "\n",
    "    # prognoza na kolejne 4 kwartały\n",
    "    future_forecast = model_fit.forecast(steps=4)\n",
    "\n",
    "    results.append({\n",
    "        'Wojewodztwo': woj,\n",
    "        'MAE': mae,\n",
    "        'RMSE': rmse,\n",
    "        'Prognoza_nast_Q1': future_forecast.iloc[0],\n",
    "        'Prognoza_nast_Q2': future_forecast.iloc[1],\n",
    "        'Prognoza_nast_Q3': future_forecast.iloc[2],\n",
    "        'Prognoza_nast_Q4': future_forecast.iloc[3],\n",
    "    })\n",
    "\n",
    "results_df = pd.DataFrame(results).sort_values(by='Wojewodztwo').reset_index(drop=True)\n",
    "results_df"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0dc75715",
   "metadata": {},
   "source": [
    "*Wyniki: Tabela z prognozami inflacji oraz wskaźnikami jakości prognoz (MAE, RMSE) dla każdego województwa.*\n",
    "\n",
    "---\n",
    "\n",
    "#### Wykres: Porównanie błędów prognoz MAE i RMSE"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "d0dfa5367282315e",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-17T13:35:38.576182Z",
     "start_time": "2025-06-17T13:35:38.410914Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 57296 characters]",
      "text/plain": [
       "<Figure size 1600x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "labels = results_df['Wojewodztwo']\n",
    "x = np.arange(len(labels))\n",
    "width = 0.35\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(16,6))\n",
    "rects1 = ax.bar(x - width/2, results_df['MAE'], width, label='MAE', alpha=0.8)\n",
    "rects2 = ax.bar(x + width/2, results_df['RMSE'], width, label='RMSE', alpha=0.8)\n",
    "\n",
    "ax.set_ylabel('Błąd')\n",
    "ax.set_title('MAE i RMSE prognoz inflacji w województwach')\n",
    "ax.set_xticks(x)\n",
    "ax.set_xticklabels(labels, rotation=90)\n",
    "ax.legend()\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a35f8d95",
   "metadata": {},
   "source": [
    "*Wizualizacja: Poziom błędów prognoz w regionach.*\n",
    "\n",
    "---\n",
    "\n",
    "#### Wykres: Heatmapa prognozowanych wzrostów inflacji w kolejnych kwartałach"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "d4df04162d14a7b1",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-17T13:37:03.112381Z",
     "start_time": "2025-06-17T13:37:02.918639Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 119200 characters]",
      "text/plain": [
       "<Figure size 1600x700 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "results_df_heatmap = results_df\n",
    "future_cols = ['Prognoza_nast_Q1', 'Prognoza_nast_Q2', 'Prognoza_nast_Q3', 'Prognoza_nast_Q4']\n",
    "\n",
    "if results_df_heatmap[future_cols[0]][0] > 100:\n",
    "    for col in future_cols:\n",
    "        results_df_heatmap[col] = results_df_heatmap[col] - 100\n",
    "\n",
    "plt.figure(figsize=(16,7))\n",
    "sns.heatmap(\n",
    "    results_df_heatmap.set_index('Wojewodztwo')[future_cols],\n",
    "    annot=True,\n",
    "    cmap='viridis',\n",
    "    vmin=0,\n",
    "    fmt=\".2f\",\n",
    "    linewidths=0.5,\n",
    "    linecolor='white'\n",
    ")\n",
    "plt.title('Prognozowany wzrost inflacji (%) w kolejnych kwartałach')\n",
    "plt.ylabel('Województwo')\n",
    "plt.xlabel('Kwartał')\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "46257d5d7120ecd3",
   "metadata": {},
   "source": [
    "*Heatmapa: Prognozowane różnice inflacji w regionach w kolejnych kwartałach.*\n",
    "\n",
    "---\n",
    "\n",
    "### Wizualizacja prognoz na mapie Polski"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "b2da217cf2925170",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-17T13:39:02.283866Z",
     "start_time": "2025-06-17T13:39:02.075395Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 114964 characters]",
      "text/plain": [
       "<Figure size 1600x650 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Wczytaj plik geojson z granicami województw\n",
    "gdf = gpd.read_file('wojewodztwa.geojson')\n",
    "\n",
    "# Mapowanie nazw województw\n",
    "mapping = {\n",
    "    'dolnośląskie': 'DOLNOŚLĄSKIE',\n",
    "    'kujawsko-pomorskie': 'KUJAWSKO-POMORSKIE',\n",
    "    'lubelskie': 'LUBELSKIE',\n",
    "    'lubuskie': 'LUBUSKIE',\n",
    "    'mazowieckie': 'MAZOWIECKIE',\n",
    "    'małopolskie': 'MAŁOPOLSKIE',\n",
    "    'opolskie': 'OPOLSKIE',\n",
    "    'podkarpackie': 'PODKARPACKIE',\n",
    "    'podlaskie': 'PODLASKIE',\n",
    "    'pomorskie': 'POMORSKIE',\n",
    "    'warmińsko-mazurskie': 'WARMIŃSKO-MAZURSKIE',\n",
    "    'wielkopolskie': 'WIELKOPOLSKIE',\n",
    "    'zachodniopomorskie': 'ZACHODNIOPOMORSKIE',\n",
    "    'łódzkie': 'ŁÓDZKIE',\n",
    "    'śląskie': 'ŚLĄSKIE',\n",
    "    'świętokrzyskie': 'ŚWIĘTOKRZYSKIE'\n",
    "}\n",
    "gdf['Wojewodztwo'] = gdf['nazwa'].map(mapping)\n",
    "\n",
    "# Połącz dane z prognozą z geometrią województw\n",
    "map_df = gdf.merge(results_df, on='Wojewodztwo')\n",
    "map_df['Prognoza'] = map_df[['Prognoza_nast_Q1', 'Prognoza_nast_Q2', 'Prognoza_nast_Q3', 'Prognoza_nast_Q4']].mean(axis=1)\n",
    "\n",
    "# Wizualizacja\n",
    "fig, ax = plt.subplots(1, 1, figsize=(16, 6.5))\n",
    "map_df.plot(column='Prognoza', cmap='viridis', linewidth=0.8, ax=ax, edgecolor='0.8', legend=True)\n",
    "ax.set_title('Prognozowana inflacja w najbliższym kwartale (wg województw)', fontdict={'fontsize':16})\n",
    "ax.axis('off')\n",
    "\n",
    "# Etykiety\n",
    "for idx, row in map_df.iterrows():\n",
    "    plt.annotate(f\"{row['Prognoza']:.2f}\",\n",
    "                 xy=(row['geometry'].centroid.x, row['geometry'].centroid.y),\n",
    "                 horizontalalignment='center', fontsize=9)\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ec8a4a734024da35",
   "metadata": {},
   "source": [
    "*Mapa: Prognozowane średnie wartości inflacji w nadchodzących kwartałach.*\n",
    "\n",
    "---\n",
    "\n",
    "## 4. Wyniki obliczeń\n",
    "\n",
    "- Dane obejmujące lata 2005–2024 wykazują umiarkowaną zmienność wskaźnika inflacji w skali kraju i regionów, a także delikatną sezonowość kwartalną (najwyższe wartości na początku roku).\n",
    "- W analizowanym okresie wyraźny wzrost inflacji (lata 2021–2023) był związany z globalnymi zjawiskami gospodarczymi (np. pandemia COVID-19), co odnotowano we wszystkich województwach.\n",
    "- Najtrafniejsze prognozy (najniższe MAE i RMSE) uzyskano dla województw o stabilniejszym przebiegu inflacji (dolnośląskie, opolskie, podkarpackie, śląskie).\n",
    "- Największą prognozowaną dynamikę inflacji w najbliższych czterech kwartałach odnotowano w województwach lubuskim, pomorskim, łódzkim oraz kujawsko-pomorskim.\n",
    "- Wyniki prognoz potwierdzają, że inflacja w Polsce ma w dużej mierze charakter ogólnokrajowy, a różnice regionalne są stosunkowo niewielkie.\n",
    "\n",
    "---\n",
    "\n",
    "## Podsumowanie i wnioski\n",
    "\n",
    "Przeprowadzona analiza umożliwiła szczegółowe zbadanie dynamiki inflacji w polskich województwach w latach 2005–2024 oraz opracowanie wiarygodnych prognoz na kolejne kwartały. Dane wykazały umiarkowaną zmienność i sezonowość wskaźnika inflacji, a także silny wpływ czynników ogólnokrajowych na przebieg procesów inflacyjnych. Modele ARIMA pozwoliły uzyskać dobrej jakości prognozy dla większości regionów. Wizualizacja wyników na mapie Polski ułatwia intuicyjne porównanie sytuacji w poszczególnych województwach.\n",
    "\n",
    "Należy pamiętać, że prognozy opierają się na założeniu kontynuacji dotychczasowych trendów i nie uwzględniają potencjalnych, nieprzewidywalnych zdarzeń przyszłych. W przyszłych badaniach warto rozważyć uwzględnienie dodatkowych zmiennych makroekonomicznych oraz alternatywnych metod prognostycznych dla jeszcze lepszego odwzorowania procesów inflacyjnych w Polsce."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
