You might not be aware of this, but you have a higher probability of attending (multiple) marriages in 2022 than in previous years, so make sure you have a sufficiently filled wardrobe for all the parties ahead. During covid-19 local restrictions prohibited the attendance of marriages in many countries. Marriages were only allowed in small groups, and many were postphoned or cancelled as a result. Therefore we expect a catch-up of postponed marriages in 2022. But how much weddings do you have to prepare for?

In this blog we use timeseries analyses to model the trend in Dutch marriages and extrapolate this to the first two Covid-19 years (2020 and 2021). Doing so we are able to shed some light on the expected amount of marriages postponed, and what might be ahead of us in 2022, of course dependent on local restrictions next year. We use public available data provided by Statistics Netherlands on the number of marriages in past years.

Setting up our toolbox

First, we set up our workbook environment with the required packages to perform timeseries analyses. Besides the basics for data handling (pandas, numpy) and graphics (seaborn and mathplotlib) we use specific packages for our task at hand:

Load preprocessed data

The initial dataset that Statistics Netherlands provides has data on weekday level. As we do not require that level of granularity we performed several data cleaning steps to have data on weeklevel from 1995 untill 2019. Aggregating the dataset to weeks instead of using weekday level also has a major advantage: in timeseries you are often faced with multiple seasonal effects in your data. Hence, you can imagine that getting married on a Friday is more attractive than on a Tuesday. The same holds for weeks and months. Fitting a timeseries model with multiple seasonal effects can be quite complicated. And, we do not need predictions on a day-level to answer our main question. Therefore we aggregate to weeks.

Next we removed outliers from our dataset. As we explain in more detail in this article people tend to get married on specific magical dates like '2012-12-12' or '2008-08-08', a calendar heatmap clearly displays most wanted marriage dates. As a result you are faced with large spikes in your data that are impossible to model. Values above 1.5 times the interquartile range were substituted by the median value of that month and year. Preprocessed data can be downloaded here. As you can see we have years, weeknumbers (iso), the date on which the week starts and the total number of marriages in that week.

Exploratory data analysis

So, let's dive into the dataset we have and see if we can get some understanding on the trend and seasonal effects. Yes, there are many metrics we can use, but the most appealing method is to show a visual of Dutch marriages by week from 1995 - 2019. Straight away we see a very volatile dataset. Within a year there seem to be two spikes, probably one just before the summer holidays and one after. On a higher level we observe a downward trend in the absolute number of marriages.

To get a better view on the variance across years and weeks we draw boxplots for both. For years we see that the variance before entering this century was somewhat higher than it is in recent years. See for instance 1997, the size of the colored box (the interquartile range) is much bigger than recent years. When we look at weekdata you can now clearly see the popularity of marriages just before and after the summer holidays. In the first week of a year the number of marriages is at the lowest of the year with hardly any differences between years.

Preparing for timeseries analyses

Now that we've got some understanding of the high level trend and what happens from year to year, it's time to perform some analysis. Using the TSA class from statsmodels we can break down the data into a trend, a seasonal effect and the remaining data points (noise). Why is this important? In timeseries modeling it is best practice to work with a so-called stationary dataset. This means that the way in which all the different parts (trend, seasonal, noise) lead to the observed values do not change over time; or formulated differently: the observed values are the result of a certain formula. This formula can be additive or multiplicative which means that the different parts of the formula will be added or multiplied. Both the trend and the seasonality can be additive or multiplicative. An additive trend indicates a linear trend while multiplicative indicates a curved trend line. When the seasonality is additive it means that the seasonality stays the same over time. With multiplicative seasonality the seasonality peaks are increasing or decreasing over time. The model parameter in the seasonal_decompose function refers to the type of seasonal component.

When dealing with a non-stationary dataset transformations need to be done to reach a stationary dataset. Many timeseries libraries do this by default. Let's take a look at our data.

As you can see in the output of seasonal_decompose there is a downward trend, mainly for early years. Next we see the isolated distinct seasonal effect and at the bottom the remaining data points. In the noise we do not see any pattern, which is good because otherwise the number of marriages would be hard to model. We can perform a statistical test to see if we are dealing with a stationary dataset. The most widely used test for stationarity is the 'Augmented Dickey-Fuller test'. It determines how strongly a timeseries is defined by a trend. The null hypothesis for the ADF-test is that the time series is not stationary, so the formula of observed values is changing over time. If the ADF-test results in a p-value below 0.05 we are dealing with a stationary dataset.

Alternatively we can also use the 'Kwiatkowski-Phillips-Schmidt-Shin' (KPSS) test, which will test the null hypothesis that a trend is stationary. The KPSS test differs from the ADF test in the sense that it tests for stationarity of a serie around a trend. So the observed values may increase or decrease over time, as long as the formula leading up to the observed values remains the same.

In the output of both the ADF- and KPSS- test you can see that our dataset is stationary. This means that no transformations are necessary for this dataset.

Timeseries modeling

Next, we are going to start modeling. We use the DARTS library to model our timeseries as this library embeds many popular methods. DARTS requires a timeseries object with a date and an observed value. An overview of all available forecasting models within this library can be found here. Next we split our dataset into a train part (1995-2018) and a validation year (2019) to see how our model performs.

DARTS: ARIMA-model

A classic when it comes to timeseries modeling is the 'autoregressive integrated moving average' analysis, or ARIMA. Within DARTS you can either use ARIMA or Auto-ARIMA, which performs a grid-search for best results. We already learned that we have a stationary dataset, that it contains seasonal characteristics and that it has a small downward trend. There are various ways to get a notion of what values to use for best results. An Auto-ARIMA model is able to use a brute-force gridsearch on available parameters. What we know is that our dataset has a clear seasonal effect, every 52 week we roughly observe the same pattern. We provide that information to the model and keep all other parameters at their defaults.

It will take some time for an Auto-ARIMA model to finish. You can decrease the number of iterations for each run or use an alternative method (method='nm' for the Nelder-Mead approach) to speed things up. But if you happen to have a large computing cluster at your disposal and half an hour to spare you can pretty much stick to the default settings. After about 20 minutes the AIC is not decreasing significantly and we are left with a model that produces a 12.4% average error rate on the validation dataset, roughly 150 marriages a week. Below we've put the forecast on top on the actual values to get a better feeling of the difference the model produces; please note: we did not train on 2020. Overall the predicted values are lower than the actual values and the model seems to find it difficult to predict the peaks for spring and september.

We feel there is room for improvement, so we will test a range of different models to see if we can improve this first result.

DARTS: Exponential Smoothing

The next method to forecast future marriages is Exponential Smoothing. Like ARIMA the Exponential Smoothing model is mainly using past observations but it also uses a decreasing weight for those observations. So the further an observation is from today, the lower the weight of that observation is for the prediction of tomorrow. It has the ability to account for seasonality and trends in the data, so it might be very suitable for our dataset. We already know from the seasonal decomposition plots that the additive seasonality works very well. As for the estimated trend we use so-called dampening because the main marriages trend we saw earlier is not a straight linear line downwards but it flattens out at the end.

With the Exponential Smoothing model an average percentage error of 8.62% has been reached, which is certainly not bad. In the visual below it is clear that the model is able to predict the spring peaks better, and also the september peak is getting closer. So, it is clear that this model is much better than Auto-ARIMA but still has an average error of 102 marriages per week.

DARTS: Prophet

Next in line is Facebook Prophet. This architecture received quite some attention a few years ago, So I'm curious if we can furter improve results. The model uses an additive approach for predicting the next case and has options to provide holiday information for best seasonal fits. According to the characteristics of this model it should work well with our dataset: strong seasonal effects, a great outlier handler and works best with quite some historical data.

Prophet has a MAPE of 9.8%, a bit higher than the Exponential Smoothing model. In the visual below you can see that the prediction is more smooth than previous models. However, the predictions for the September marriages are still too low.

DARTS: NBEATS

DARTS has many more models to play around with. The last model we are testing in this blog is a deep learning model based on the NBEATS architecture or Neural Basis Expansion Analysis for Interpretable Time Series Forecasting. We first heard about NBEATS in this data Skeptic podcast and decided to give it a go. The architecture works very different than models we've used before. The model will take an entire window of past values, and computes many future values in one iteration. It will not only predict forwards but also backwards (backcasting). Then it will choose a different window to minimise the prediction error untill no further improvement can be made.

After 50 epochs of training we reach an average percentage error of 9.85% which is comparable to earlier models. We played around with different parameters of the NBEATS model but failed to produce a stunning result. From the visual below it is clear that the model has difficulty in the months leading up to spring, from the summer onwards the prediction is almost flawless.

And the winner is...

This means we have a winning timeseries model for predicting Dutch marriages based upon data from 1995 to 2019. The Exponential Smoothing model has the lowest MAPE of all tested models. From the graph below it seems that this model is better able to accomodate the peaks in the number of marriages in june/july and september than the other models are.

Forecast for 2020 and 2021

Now that we have our winning model we can predict future marriages for 2020 and 2021. The model is not aware of the covid-19 pandemic and therefore will keep on predicting a marriagerate based on past observations. By now we know better ;) With these predictions we can calculate the difference between the predicted number of marriages and the actual marriages that took place. We use the winning model to predict cases for 2020 and 2021.

Unfortunately, Statistics Netherlands only provides the marriages at a detailed level, such as the marriages on a daily basis, once every two years. That means that at the moment marriages for 2020 and 2021 are only provided at a less detailed level, i.e. on a monthly basis. Since our main goal was to estimate the number of postponed marriages for the first two Covid-19 years and not specifically in a certain week, we will make a cumulative comparison by year.

In the dataframe above we have collected the monthly marriages provided by Statistics Netherlands. Below we match the predicted numbers for the same years and add a cumulative column for both. Both are then plotted againts each other, the gap between the prediction and the actuals is the amount of maariages parties we've missed. It might not seem like much to the naked eye, but wait till you see the numbers.

The data available rusn until the 1st of November for 2021, so we sum the months for which we have full availability of data and arrive at a conclusion: we've missed a little over 7.300 marriages!

Expand your wardrobe quickly, because around 7000 marriages have to be catched up

According to our predictions there were 7370 fewer marriages concluded than there would otherwise if Covid-19 hadn't come up. Probably part of these people did get married already, maybe with fewer people than planned or with some restrictions. However, we think that there are also many people that postponed their marriage until they can celebrate it the way they would like to. If this would be the case, we are going to have a great festive year, fingers crossed. So in short: just make sure you have plenty of party outfits in your closet!