Housing, 1st act

brief outline, I will:

  • Discuss about recent refloating of an article from 2018 and the capability to make savings in Spain
  • Share what I took into account when choosing a mortgage, which could be useful to you (luckily, you can). Future me: next post

So then, let's begin.

Housing 1st act: The meme that became viral

the-meme

I don't know why it became trendy recently, because the article was written in 2018. However, the big picture is the same nowadays (in terms of job insecurity and morons people using the same argument).

First issue: salaries

Unfortunately unemployment rate among the youth in Spain is still extreme. This is followed and helps keeping crappy salaries and stability, ofc. If we check the income we can see that it is more or less the same than it was 10 years ago (but prices aren't).
Below I show the temporal evolution of youth's (16 to 24 y/o) mean income, consumer price index and % unemployment across the same population.

In [1]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import warnings 
warnings.filterwarnings('ignore')
sns.set_context('talk')

ine_kws = dict(sep=';', decimal=',', thousands='.', encoding='latin-1')
f, ax = plt.subplots(ncols=1, nrows=3, figsize=(12,15), sharex=True)
( # income 
    pd.read_csv('../data/mean_net_income_youth.csv', **ine_kws)
    .sort_values(by='Periodo')
    .plot(x="Periodo", y='Total', label='net income (16~24 y/o)', 
          xlabel='date', legend=False, ax=ax[0])
)

# IPC
df = pd.read_csv('../data/ipc.csv', **ine_kws)
df = df.iloc[::-1].reset_index(drop=True) # flipping upside down
boundaries = df[(df.Periodo=='2008M01')|(df.Periodo=='2020M12')].index
ax[1].plot(
    np.arange(2008, 2021, 1/12), # x axis vector
    (100*df.loc[
        boundaries[0]:boundaries[1], 'Total'
    ]/df.loc[boundaries[0], 'Total']).values-100,
    color='tab:purple', label='ipc % increase since 2008'
)

### unemployment rate
df = pd.read_csv('../data/desempleo_jovenes.csv', **ine_kws)
df = df.iloc[::-1].reset_index(drop=True) # flipping upside down
boundaries = df[(df.Periodo=='2008T1')|(df.Periodo=='2020T4')].index
ax[2].plot(
    np.arange(2008, 2021, 1/4), # x axis vector
    df.loc[boundaries[0]:boundaries[1], 'Total'].values,
    color='tab:red', label='unemployment rate'
)

# customize y_label and legends
for i, label in enumerate(['mean net income (€)','% IPC incr. since 2008', '% unemployment rate']):
    ax[i].set_ylabel(label);

income source
IPC source
unemployment source

Also, salary distribution tends to be quite wide (as always, remember that mean income can be deceiving). I think it is quite clear that making significant savings is almost impossible for a big portion of the youth. Concomitantly, getting a mortgage is not an easy business. Banks are not really willing to lend such an amount of money to someone that has job insecurity & low income.

Second issue: property price

Prices in big cities are crazy high. We could digress about Aznar's construction bubble (ladrillazo) here but I won't for simplicity. Price's are rising again after the last (non-covid) financial crisis.

source

Third issue: Commitment

Buying an apartment is a big step and it requires other casualties, like having a stable partner and finding an apartment that will fulfill your needs for the foreseeable future. In other words, given that it will take more than 20 years to pay the debt, if you plan to have a child probably you will look for a place with 2 or 3 rooms rather than a more affordable loft. This raises the price. Actually, in Barcelona it means >250k € in most of the cases (this is probably such an underestimation). Which means you initially need 50k for the mortgage (20% of its value) and extra 12.5k for the taxes (at least) + other costs. 32K € each.

Closing:

(I think) A considerable number of people are not buying properties because they can't afford the initial payment (>30k) or they cannot get a mortgage approved. Formulating this kind of title in an article could be due:

  • clickbait purposes.
  • Being a douche unaware of reality AND/OR a complete lack of empathy.

Some older people still think that this current scenario is still the same that they experienced 25~40 years ago (when willing to work was enough and one could pay for a mortgage in 7~15 years). Also, their current job market might be quite different from the youth's one.
I'll take this sad opportunity to make a salary ridge/joy plot across age ranges reusing seaborn sample code (source data).

In [5]:
# blatantly copypaste seaborn ridge
# read ine data
deciles = pd.read_csv('../data/deciles_all.csv', **ine_kws)
sns.set_theme(style="white", rc={"axes.facecolor": (0, 0, 0, 0)})
# Initialize the FacetGrid object
pal = sns.cubehelix_palette(5, rot=-.25, light=.6)
g = sns.FacetGrid(deciles[deciles.Periodo==2019], row="Grupo de edad", 
                  hue="Grupo de edad", aspect=15, height=.5, palette=pal)
# Draw the densities in a few steps
g.map(sns.kdeplot, "Total",
      bw_adjust=.5, clip_on=False,
      fill=True, alpha=1, linewidth=1.5)
g.map(sns.kdeplot, "Total", clip_on=False, color="w", lw=2, bw_adjust=.5)
g.map(plt.axhline, y=0, lw=2, clip_on=False)
# Define and use a simple function to label the plot in axes coordinates
def label(x, color, label):
    ax = plt.gca()
    ax.text(-.05, .15, label[:-5], fontweight="bold", color=color,
            ha="left", va="center", transform=ax.transAxes)
g.map(label, "Total")
# Set the subplots to overlap
g.fig.subplots_adjust(hspace=-.25)
# Remove axes details that don't play well with overlap
g.set_titles("")
g.set(yticks=[], xlabel='gross salary / month')
g.despine(bottom=True, left=True);
In [6]:
# youth salary distribution per year
sns.set_theme(style="white", rc={"axes.facecolor": (0, 0, 0, 0)})
# Initialize the FacetGrid object
pal = sns.cubehelix_palette(14, rot=-.25, light=.6)
g = sns.FacetGrid(
    deciles[deciles["Grupo de edad"]=="De 16 a 24 años"], 
    row="Periodo", hue="Periodo", aspect=15, height=.5, palette=pal
)
# Draw the densities in a few steps
g.map(sns.kdeplot, "Total",
      bw_adjust=.5, clip_on=False,
      fill=True, alpha=1, linewidth=1.5)
g.map(sns.kdeplot, "Total", clip_on=False, color="w", lw=2, bw_adjust=.5)
g.map(plt.axhline, y=0, lw=2, clip_on=False)
# Define and use a simple function to label the plot in axes coordinates
def label(x, color, label):
    ax = plt.gca()
    ax.text(-.05, .15, label, fontweight="bold", color=color,
            ha="left", va="center", transform=ax.transAxes)
g.map(label, "Total")
# Set the subplots to overlap
g.fig.subplots_adjust(hspace=-.25)
# Remove axes details that don't play well with overlap
g.set_titles("")
g.set(yticks=[], xlabel='gross salary / month')
g.despine(bottom=True, left=True);

So then, young nini(NEET), why haven't you made some savings this last decade?
I'll talk about mortgages in my next post, just in case it can shed some light to those who managed to be eligible.

Cheers!

Show Comments