Close
Wskaźnik nagromadzenia odpadów, a osobiste, przeciętne wydatki – prognozowanie z zastosowaniem modelu wektorowej autoregresji

Wskaźnik nagromadzenia odpadów, a osobiste, przeciętne wydatki – prognozowanie z zastosowaniem modelu wektorowej autoregresji

Rok 2020 to kolejny rok, w którym wskaźnik masowy nagromadzenia odpadów odniesiony do jednego mieszkańca, czyli ogólnie mówiąc wskaźnik pokazujący ile odpadów wytwarza każdy z nas, osiągnął kolejny rekord. Na jednego mieszkańca przypadało w 2020 r. średnio 342 kg wytworzonych odpadów komunalnych, co oznacza wzrost o około 10 kg w porównaniu z rokiem poprzednim. A jeszcze w 2010 roku wartość tego wskaźnika wynosiła około 263 kg. W ciągu dziesięciu lat statystyczny mieszkaniec Polski zwiększył ilość wytwarzanych odpadów komunalnych o blisko 80 kg. I co najgorsze w tym wszystkim, to że ciągle wytwarzamy jako Polacy mniej niż  statystyczny Europejczyk. Dla przypomnienia średnia unijna wynosi 502 kg [2]

Z kolei jak wynika z raportu „Sytuacja gospodarstw domowych w 2020 r. w świetle badania budżetów gospodarstw domowych”[1] opublikowanego przez Główny Urząd Statystyczny sytuacja materialna gospodarstw domowych nieznacznie poprawiła się pomimo pandemii COVID-19. Gospodarstwa domowe osiągnęły wyższe dochody. Nadal jednak utrzymuje się relatywnie duże zróżnicowanie przeciętnych miesięcznych dochodów pomiędzy różnymi grupami społeczno-ekonomicznymi. Oczywiście wzrost dochodów przekłada się na wzrost wydatków, choć należy zauważyć, że przeciętne miesięczne wydatki na 1 osobę w gospodarstwach domowych w 2020 roku były realnie niższe o 6,5% (nominalnie o 3,4%) od wydatków z 2019 roku. Wydajemy więcej przede wszystkim na dobra konsumpcyjne, żywność, napoje bezalkoholowe itp. Także nie dziwi fakt, że i odpadów komunalnych nam przybywa.

Wykres pokazujący przeciętne miesięczne wynagrodzenie oraz współczynnik nagromadzenia odpadów w latach 2000-2020
Rys. 1. Przeciętne. miesięczne wynagrodzenie oraz średnia ilość wytwarzanych odpadów komunalnych na osobę w ostatnim dwudziestoleciu

Model wektorowej autoregresji (VAR)

Postanowiłem zatem sprawdzić, jak sprawdzi się model wektorowej autoregresji w prognozowaniu przyszłych wartości tych wskaźników. Dla nie wtajemniczonych model wektorowej autoregresji, określany często w literaturze jako VAR [3] (ang. vector autoregression), jest stochastycznym modelem ekonometrycznym szeroko stosowanym w ekonomii czy naukach przyrodniczych. Przykłady zastosowania modeli VAR można znaleźć zarówno w literaturze polskiej, jak i w światowej. Model VAR uogólnia model autoregresji z jedną zmienną (jednowymiarową) na wielowymiarowe szeregi czasowe. K-wymiarowy model VAR rzędu p oznaczony jako VAR(p) dla dwóch zmiennych i jednym opóźnieniu (czyli VAR(1)) można przedstawić jako następujący układ równań:

𝑦1,𝑡=𝑐1+𝜙11,1𝑦1,𝑡−1+𝜙12,1𝑦2,𝑡−1+𝜀1,𝑡
𝑦2,𝑡=𝑐2+𝜙21,1𝑦1,𝑡−1+𝜙22,1𝑦2,𝑡−1+𝜀2,𝑡

gdzie:

– 𝑦k,𝑡 jest k wymiarowym szeregiem czasowym jednowymiarowej zmiennej,
– 𝜙𝑖𝑖,𝑙 określają wpływ 𝑙-tego opóźnienia zmiennej 𝑦i na nią samą,
– 𝜙𝑖𝑗,𝑙 określają wpływ 𝑙-tego opóźnienia zmiennej 𝑦𝑗 na zmienną 𝑦𝑖,
– współczynniki 𝜀1,𝑡 i 𝜀2,𝑡 stanowią błąd (szum biały), który może być skorelowany.

Dane do analizy

Dane do analizy zostały pobrane z Banku Danych Lokalnych [4] i stanowią roczne wartości przeciętnych miesięcznych wydatków na 1 osobę w gospodarstwie domowym oraz wskaźnika nagromadzenia odpadów przypadający na 1 osobę w gospodarstwie domowym w ostatnim dwudziestoleciu, czyli w latach 2000-2020. Na rysunku 1 przedstawiono jak kształtowały się te dwa wskaźniki na przestrzeni oznaczonych lat.

Środowisko analizy

Do przeprowadzenia analizy wykorzystano środowisko Jupyter Notebook, a w nim bibliotekę statsmodels [5], która dostarcza szeregu klas i funkcji do szacowania wielu różnych modeli statystycznych, w tym także modelu wektorowej autoregresji [6]

Zaczynamy

Wczytujemy zatem potrzebne biblioteki oraz pozyskane dane do analizy przy okazji nadając im odpowiedni typ szeregu czasowego datetime64 [7] oraz określając ich częstotliwość jako roczną.

# Load basic libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

# Load specific forecasting tools. From statsmodels.tsa.api import VAR model
from statsmodels.tsa.vector_ar.var_model import VAR, VARResults
from statsmodels.tsa.stattools import adfuller
from statsmodels.tools.eval_measures import rmse

# Ignore harmless warnings
import warnings
warnings.filterwarnings("ignore")

# Load datasets
df = pd.read_csv("wskaznik_nagromadzenia_a_wydatki_na_osobe.csv", sep=';', decimal = ',', index_col=[0], parse_dates=True)
df.index.freq = 'A-DEC'
df.index.names = ['Year']

Krótki rzut oka na statystyczne parametry opisowe naszych zmiennych. Jako PCE oznaczono przeciętne, miesięczne wydatki osobiste, a jako MWAR wskaźnik nagromadzenia odpadów. Mamy zatem po 21 danych w obu seriach, średnia wartość dla wydatków osobistych na przestrzeni 20 ostatnich lat wynosi 931 zł, a średni wskaźnik nagromadzenia odpadów 277 kg na mieszkańca na rok.

Rys. 2. Statystyczne parametry opisowe danych przeciętnych, miesięcznych wydatków oraz ilości wytwarzanych odpadów komunalnych na jedną osobę

Czy szeregi są stacjonarne?

Przystępując do przeprowadzenia analizy z wykorzystaniem modelu autoregresyjnego musimy pamiętać o kilku rzeczach. Na początku należy sprawdzić, czy szeregi czasowe naszych zmiennych endogenicznych są stacjonarne. W tym celu skorzystałem z rozszerzonego testu Dickeya-Fullera (tzw. test ADF – ang. Augmented Dickey-Fuller test), który służy statystycznej weryfikacji stacjonarności i jest zaimplementowany w bibliotece stattools [8]. Generalnie jeżeli obliczona wartość statystyki testu ADF jest większa niż wartość krytyczna to nie ma podstaw do odrzucenia hipotezy zerowej o niestacjonarności badanej zmiennej. Jeśli obliczona wartość statystyki testu ADF jest mniejsza niż wartość krytyczna, hipotezę zerową odrzucamy na rzecz stacjonarności zmiennej.

def adf_test(series,title=''):
    """
    Pass in a time series and an optional title, returns an ADF report
    """
    print(f'Augmented Dickey-Fuller Test: {title}')
    
    result = adfuller(series.dropna(),autolag='AIC') # .dropna() handles differenced data
    
    labels = ['ADF test statistic','p-value','# lags used','# observations']
    out = pd.Series(result[0:4],index=labels)

    for key,val in result[4].items():
        out[f'critical value ({key})']=val
        
    print(out.to_string())          # .to_string() removes the line "dtype: float64"
    
    if result[1] <= 0.05:
        print("Strong evidence against the null hypothesis")
        print("Reject the null hypothesis")
        print("Data has no unit root and is stationary")
    else:
        print("Weak evidence against the null hypothesis")
        print("Fail to reject the null hypothesis")
        print("Data has a unit root and is non-stationary")
        
adf_test(df['MWAR'],title='Waste')
adf_test(df['PCE'],title='Spending')

Jak się okazało zmienna endogeniczna – wskaźnik nagromadzenia odpadów – okazała się szeregiem niestacjonarnym, co wymusiło przeprowadzenie różnicowania szeregów czasowych i ponowne wykonanie testu ADF. To jednak również nie wystarczyło, konieczne było przeprowadzenie powtórnego różnicowania. Dopiero na tym etapie ustabilizowano szeregi czasowe, niestety zostało to okupione utratą wartości z dwóch początkowych lat. W rezultacie do dalszego szacowania modelu wykorzystano drugie różnice zmiennych.

Podział na zbiór uczący i testowy

Kolejnym krokiem był podział posiadanego zbioru na zbiór uczący oraz testowy. Jako zbiór uczący wybrano początkowe 17 wartości, a zbiór testowy stanowiły wartości z roku 2019 oraz 2020.

nobs=2
train, test = df_transformed[:-nobs], df_transformed[-nobs:]

Rząd i parametry modelu VAR

Wybór początkowego rzędu dla modelu VAR oparty został o kryterium informacyjne Akaikego (AIC) [9] oraz bayesowskie kryterium informacyjne Schwartza (BIC) [10].

for i in range(5):
    model = VAR(train)
    results = model.fit(i)
    print('Order =', i)
    print('AIC: ', results.aic)
    print('BIC: ', results.bic)
    print('HQIC: ', results.hqic, '\n')
    print()

Najmniejsze wartości dla wyznaczonych kryterium wskazały na drugi rząd opóźnienia. Parametry modelu VAR(2) przedstawiono poniżej.

Zdecydowanie zauważamy, ze większościowo zmiany predyktora nie są związane ze zmianami w odpowiedzi. Celem stwierdzenia, czy szereg czasowy wskaźnika nagromadzenia odpadów jest użyteczny w prognozowaniu szeregu czasowego wydatków osobistych przeprowadziłem liniowy test przyczynowości Grangera. Postawiona hipoteza zerowa oznacza brak zależności przyczynowej w sensie Grangera jednej zmiennej od drugiej, w przeciwieństwie do hipotezy alternatywnej która oznacza przyczynową zależność, czyli to, ze wartość zmiennej w jednym szeregu przy określonym opóźnieniu może być znacząca dla prognozowania wartości zmiennej w drugim szeregu w późniejszym okresie [11]. Oczywiście hipotezę zerową odrzucamy dla p-value < 0.05.  Wynik testu wskazał, ze wydatki osobiste nie wykazują zależności przyczynowej z wskaźnikiem nagromadzenia odpadów,

ale pomiędzy wskaźnikiem nagromadzenia odpadów a wydatkami osobistymi takiej przyczynowości możemy się doszukać.

Przeprowadzono także test Portmanteau do zbadania czy występuje autokorelacja reszt po dopasowaniu modelu. Dla m>2 wartość p < 0.05, tak więc nie mamy do czynienia z autokorelacją reszt.

Testujemy model

Zatem można teraz przejść do przetestowania zbudowanego modelu wykorzystując do tego zbiór testowy i funkcję forecast. Do funkcji przekazać należy wprost rząd opóźnienia. A z powodu tego, ze narzędzie nie określa wprost indeksu czasowego musimy to zrobić ręcznie.

lag_order = results.k_ar
z = results.forecast(y=train.values[-lag_order:], steps=2)
idx = pd.date_range('31/12/2019', periods=2, freq='A-DEC')
df_forecast = pd.DataFrame(z, index=idx, columns=['Spending2d','Waste2d'])

Oczywiście otrzymane wartości stanowią drugie różnice zmiennych, zatem celem porównania należało wykonać odwrotne podwójne różnicowanie.

# Add the most recent first difference from the training side of the original dataset to the forecast cumulative sum
df_forecast['Spending1d'] = (df['PCE'].iloc[-nobs-1]-df['PCE'].iloc[-nobs-2]) + df_forecast['Spending2d'].cumsum()

# Now build the forecast values from the first difference set
df_forecast['PCE_Forecast'] = df['PCE'].iloc[-nobs-1] + df_forecast['Spending1d'].cumsum()

# Add the most recent first difference from the training side of the original dataset to the forecast cumulative sum
df_forecast['Waste1d'] = (df['MWAR'].iloc[-nobs-1]-df['MWAR'].iloc[-nobs-2]) + df_forecast['Waste2d'].cumsum()

# Now build the forecast values from the first difference set
df_forecast['MWAR_Forecast'] = df['MWAR'].iloc[-nobs-1] + df_forecast['Waste1d'].cumsum()

Oszacowanie mierników

W rezultacie otrzymano wartości z modelu, które porównano z wartościami zbioru testowego współczynnika nagromadzenia odpadów i przeciętnych, osobistych, miesięcznych wydatków. Błąd oszacowano za pomocą RMSE (ang. root mean square error) [1] oraz innych statystycznych mierników, takich jak: MAPE, MAE, MPE.  

from statsmodels.tsa.stattools import acf
def forecast_accuracy(forecast, actual):
    mape = np.mean(np.abs(forecast - actual)/np.abs(actual))  # MAPE
    me = np.mean(forecast - actual)             # ME
    mae = np.mean(np.abs(forecast - actual))    # MAE
    mpe = np.mean((forecast - actual)/actual)   # MPE
    rmse = np.mean((forecast - actual)**2)**.5  # RMSE
    corr = np.corrcoef(forecast, actual)[0,1]   # corr
    mins = np.amin(np.hstack([forecast[:,None], 
                              actual[:,None]]), axis=1)
    maxs = np.amax(np.hstack([forecast[:,None], 
                              actual[:,None]]), axis=1)
    minmax = 1 - np.mean(mins/maxs)             # minmax
    return({'mape':mape, 'me':me, 'mae': mae, 
            'mpe': mpe, 'rmse':rmse, 'corr':corr, 'minmax':minmax})

print('Forecast Accuracy of: PCE')
accuracy_prod = forecast_accuracy(df_forecast['PCE_Forecast'].values, df['PCE'][-nobs:])
for k, v in accuracy_prod.items():
    print(k, ': ', round(v,4))

print('\nForecast Accuracy of: MWAR')
accuracy_prod = forecast_accuracy(df_forecast['MWAR_Forecast'].values, df['MWAR'][-nobs:])
for k, v in accuracy_prod.items():
    print(k, ': ', round(v,4))
Porównanie wartości otrzymanych z modelu ze zbiorem wartości testowych dla współczynnika nagromadzenia odpadów
Rys. 3. Porównanie wartości otrzymanych z modelu ze zbiorem wartości testowych dla współczynnika nagromadzenia odpadów
Porównanie wartości otrzymanych z modelu ze zbiorem wartości testowych dla przeciętnego miesięcznego wydatku personalnego
Rys. 4. Porównanie wartosci otrzymanych z modelu ze zbiorem wartości testowych dla przeciętnego miesięcznego wydatku personalnego

Wartość błędu średniokwadratowego dla współczynnika nagromadzenia odpadów wyniosła 19.614 kg przy średniej wartości 337.5 kg, z kolei dla przeciętnego miesięcznego wydatku osobistego 56.51 zł przy średniej wartości 1230.66 zł. Stąd tez względny błąd prognozowania nie przekracza 7%, przez co model prognozowania jest do przyjęcia.

Prognoza na trzy lata

Wyznaczmy zatem w oparciu o niego przyszłe wartości, np na lata 2021-2023. Jak z nich widać uzyskano dość znaczący wzrost w przypadku współczynnika nagromadzenia odpadów. Szacowana wartość parametru na koniec 31 grudnia 2021 wyniosła 346,2 kg. Z kolei w przypadku przeciętnych miesięcznych wydatków obserwujemy początkowy spadek wskaźnika w stosunku do lat ostatnich. Potem lekki wzrost. A jak będzie, to już za kilka miesięcy będziemy mogli to zweryfikować.


[1] https://stat.gov.pl/obszary-tematyczne/warunki-zycia/dochody-wydatki-i-warunki-zycia-ludnosci/sytuacja-gospodarstw-domowych-w-2020-r-w-swietle-badania-budzetow-gospodarstw-domowych,3,20.html

[2] https://ekordo.pl/statystyka-odpadowa-wg-danych-eurostatu-za-2019-r/

[3] https://en.wikipedia.org/wiki/Vector_autoregression

[4] https://bdl.stat.gov.pl/BDL/start

[5] Introduction — statsmodels

[6] Vector Autoregressions tsa.vector_ar — statsmodels

[7] Time series / date functionality — pandas 1.4.1 documentation (pydata.org)

[8] statsmodels.tsa.stattools — statsmodels

[9] https://pl.wikipedia.org/wiki/Kryterium_informacyjne_Akaikego

[10] https://pl.wikipedia.org/wiki/Bayesowskie_kryterium_informacyjne_Schwarza

[11] Test_Granger causality

[12] RMSE: Root Mean Square Error – Statistics How To

Jurand Bień

dr hab. inż., prof. Politechniki Częstochowskiej; zainteresowania: aspekty środowiskowe, gospodarowanie odpadami (praktyczne), danologia (hobbystycznie)

dr hab. inż., prof. Politechniki Częstochowskiej; zainteresowania: aspekty środowiskowe, gospodarowanie odpadami (praktyczne), danologia (hobbystycznie)

Leave a Reply

Your email address will not be published. Required fields are marked *

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.