In [1]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
In [2]:
# supply curve equation
y = 0.5*0.5 + 1

y
Out[2]:
1.25
In [3]:
# creating supply curve
df_housing_supply = pd.DataFrame(np.array([[0,1], [4, 3]]), 
                          columns=['Quantity', 'Price'])
df_housing_supply
Out[3]:
Quantity Price
0 0 1
1 4 3
In [4]:
# creating supply curve decrease
df_housing_supply_decrease = pd.DataFrame(np.array([[0,1.75], [3.75,3.625]]), 
                          columns=['Quantity', 'Price'])
df_housing_supply_decrease

#3 = 3.75*0.5 +1.75
Out[4]:
Quantity Price
0 0.00 1.750
1 3.75 3.625
In [5]:
# demand curve equation
y = -0.5*3.1 + 3

y
Out[5]:
1.45
In [6]:
#creating demand curve
df_housing_demand = pd.DataFrame(np.array([[0,3], [3.6,1.2]]), 
                          columns=['Quantity', 'Price'])

df_housing_demand
Out[6]:
Quantity Price
0 0.0 3.0
1 3.6 1.2
In [7]:
# demand curve increase equation
y = -0.5*4 + 4

y
Out[7]:
2.0
In [8]:
# creating demand curve increase
df_housing_demand_increase = pd.DataFrame(np.array([[0.4,3.8], [4, 2]]), 
                          columns=['Quantity', 'Price'])

df_housing_demand_increase
Out[8]:
Quantity Price
0 0.4 3.8
1 4.0 2.0
In [9]:
# data for plumb lines of first equilibrium
dotted_one = pd.DataFrame(np.array([[0,2], [2,2], [2,0]]), 
                          columns=['xx', 'yy'])
dotted_one
Out[9]:
xx yy
0 0 2
1 2 2
2 2 0
In [10]:
# data for plumb lines of second equilibrium
dotted_two = pd.DataFrame(np.array([[0,2.5], [3,2.5], [3,0]]), 
                          columns=['xx', 'yy'])
dotted_two
Out[10]:
xx yy
0 0.0 2.5
1 3.0 2.5
2 3.0 0.0
In [11]:
# set figure size and style
fig = plt.figure(figsize=(9,6))
sns.set_style('darkgrid')

# plot axes
plt.axvline(ymin=0.065, ymax=0.93, color='black')
plt.axhline(xmin=0.065, xmax=0.93, color='black')

# plot supply and demand curves
plt.plot('Quantity', 'Price', data=df_housing_supply, label='Supply', 
         color='tomato', zorder=1, lw=2)

plt.plot('Quantity', 'Price', data=df_housing_demand, label='Demand', 
         color='lightseagreen', zorder=1, lw=2)

plt.plot('Quantity', 'Price', data=df_housing_demand_increase, 
         label='Demand increase', color='lightseagreen', linestyle='dashed',
         zorder=1, lw=2)

# plot equilibria and plumb lines
plt.scatter(x=2, y=2, zorder=2, color='grey', s=60, label='Old equilibrium')
plt.plot('xx', 'yy', data=dotted_one, linestyle='dotted', color='grey', label='', lw=3)

plt.scatter(x=3, y=2.5, zorder=2, color='royalblue', s=60, label='New equilibrium')
plt.plot('xx', 'yy', data=dotted_two, linestyle='dotted', color='royalblue', label='', lw=3)

# plot arrows
plt.arrow(0.75, 2.625, 0.18, 0.4, width=0.015, head_width=0.13, head_length=0.13, fc='k', ec='k')
plt.arrow(3.1, 1.45, 0.18, 0.4, width=0.015, head_width=0.13, head_length=0.13, fc='k', ec='k')
# label axes
plt.xlabel('Quantity', fontsize=16)
plt.ylabel('Price', fontsize=16)

# set axes limits
plt.xlim([-0.3, 4.3])
plt.ylim([-0.3, 4.3])

# title and legend
plt.title('St. Ives Housing Market', fontsize=20, pad=30)
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, prop={'size': 13})
plt.tight_layout()
fig.savefig('st-ives-housing-market.png', dpi=180);
In [12]:
# demand curve increase equation
#y = -0.5*x + 4

# supply curve decrease equation
#y = 0.5*x + 1.75

#5.75/2
(2.875 - 1.75)/0.5
Out[12]:
2.25
In [13]:
# data for plumb lines of third equilibrium
dotted_three = pd.DataFrame(np.array([[0,2.875], [2.25,2.875], [2.25,0]]), 
                          columns=['xx', 'yy'])
dotted_three
Out[13]:
xx yy
0 0.00 2.875
1 2.25 2.875
2 2.25 0.000
In [14]:
# set figure size and style
fig = plt.figure(figsize=(12,8))
sns.set_style('darkgrid')

# ----- FIRST SUBPLOT ------
plt.subplot(1, 2, 1)

# plot axes
plt.axvline(ymin=0.065, ymax=0.93, color='black')
plt.axhline(xmin=0.065, xmax=0.93, color='black')

# plot supply and demand curves
plt.plot('Quantity', 'Price', data=df_housing_supply, label='Supply #1', 
         color='tomato', zorder=1, lw=2)

plt.plot('Quantity', 'Price', data=df_housing_demand, label='Demand #1', 
         color='lightseagreen', zorder=1, lw=2)

plt.plot('Quantity', 'Price', data=df_housing_demand_increase, 
         label='Demand #2 (increase)', color='lightseagreen', linestyle='dashed',
         zorder=1, lw=2)

# plot equilibria and plumb lines
plt.scatter(x=2, y=2, zorder=2, color='grey', s=60, label='Old equilibrium')
plt.plot('xx', 'yy', data=dotted_one, linestyle='dotted', color='grey', label='', lw=3)

plt.scatter(x=3, y=2.5, zorder=2, color='royalblue', s=60, label='New equilibrium')
plt.plot('xx', 'yy', data=dotted_two, linestyle='dotted', color='royalblue', label='', lw=3)

# plot arrows
plt.arrow(0.75, 2.625, 0.18, 0.4, width=0.015, head_width=0.13, head_length=0.13, fc='k', ec='k')
plt.arrow(3.1, 1.45, 0.18, 0.4, width=0.015, head_width=0.13, head_length=0.13, fc='k', ec='k')

# label axes
plt.xlabel('Quantity', fontsize=16)
plt.ylabel('Price', fontsize=16)

# set axes limits
plt.xlim([-0.3, 4.3])
plt.ylim([-0.3, 4.3])

# title and legend
plt.title('Situation for Locals: Increase in Demand', fontsize=18, pad=20)
plt.legend(bbox_to_anchor=(0.5, -0.4), loc=8, prop={'size': 13}, ncol=2)
plt.tight_layout()

# ----- SECOND SUBPLOT -----
plt.subplot(1, 2, 2)

# plot axes
plt.axvline(ymin=0.065, ymax=0.93, color='black')
plt.axhline(xmin=0.065, xmax=0.93, color='black')

# plot supply and demand curves
plt.plot('Quantity', 'Price', data=df_housing_supply, label='Supply #1', 
         color='tomato', zorder=1, lw=2)

plt.plot('Quantity', 'Price', data=df_housing_supply_decrease, 
         label='Supply #2 (decrease)', color='tomato', zorder=1, linestyle='dashed', lw=2)

plt.plot('Quantity', 'Price', data=df_housing_demand_increase, 
         label='Demand #2', color='lightseagreen', linestyle='dashed',
         zorder=1, lw=2)

# plot equilibria and plumb lines
plt.scatter(x=3, y=2.5, zorder=2, color='grey', s=60, label='Old equilibria')
plt.plot('xx', 'yy', data=dotted_two, linestyle='dotted', color='grey', label='', lw=3)

plt.scatter(x=2.25, y=2.875, zorder=2, color='royalblue', s=60, label='New equilibrium')
plt.plot('xx', 'yy', data=dotted_three, linestyle='dotted', color='royalblue', label='', lw=3)

# plot arrows
plt.arrow(0.5, 1.25, -0.15, 0.3, width=0.015, head_width=0.13, head_length=0.13, fc='k', ec='k')
plt.arrow(3.5, 2.75, -0.15, 0.3, width=0.015, head_width=0.13, head_length=0.13, fc='k', ec='k')

# axes labels
plt.xlabel('Quantity', fontsize=16)
plt.ylabel('Price', fontsize=16)

# axes limits
plt.xlim([-0.3, 4.3])
plt.ylim([-0.3, 4.3])

# title and legend
plt.title('Response by Locals: Decrease in Supply', fontsize=18, pad=20)
plt.legend(bbox_to_anchor=(0.5, -0.4), loc=8, prop={'size': 13}, ncol=2)
plt.tight_layout()

# ----- End of second subplot -----

# figure title
plt.subplots_adjust(top=0.84)
fig.suptitle('St. Ives Housing Market: Pre-Legislation', fontsize=20)
fig.savefig('st-ives-housing-market-pre-legislation.png', dpi=180);
In [15]:
# creating second demand curve increase
df_housing_demand_increase2 = pd.DataFrame(np.array([[0.5,4], [4,2.25]]), 
                          columns=['Quantity', 'Price'])

df_housing_demand_increase2
Out[15]:
Quantity Price
0 0.5 4.00
1 4.0 2.25
In [16]:
# demand curve increase2 equation
#y = -0.5*x + 4

# supply curve decrease equation
#y = 0.5*x + 1.75

(4.5+1.75)/2
Out[16]:
3.125
In [17]:
# data for plumb lines of forth equilibrium
dotted_four = pd.DataFrame(np.array([[0,3], [2.5,3], [2.5,0]]), 
                          columns=['xx', 'yy'])
dotted_four
Out[17]:
xx yy
0 0.0 3.0
1 2.5 3.0
2 2.5 0.0
In [18]:
# set figure size and style
fig = plt.figure(figsize=(12,8))
sns.set_style('darkgrid')

# ----- FIRST SUBPLOT -----
plt.subplot(1, 2, 1)

# plot axes
plt.axvline(ymin=0.065, ymax=0.93, color='black')
plt.axhline(xmin=0.065, xmax=0.93, color='black')

# plot supply and demand curves
plt.plot('Quantity', 'Price', data=df_housing_supply, label='Supply #1', 
         color='tomato', zorder=1, lw=2)

plt.plot('Quantity', 'Price', data=df_housing_supply_decrease, 
         label='Supply #2 (decrease)', color='tomato', zorder=1, linestyle='dashed', lw=2)

plt.plot('Quantity', 'Price', data=df_housing_demand_increase, 
         label='Demand #2', color='lightseagreen', linestyle='dashed',
         zorder=1, lw=2)

# plot equilibria and plumb lines
plt.scatter(x=3, y=2.5, zorder=2, color='grey', s=60, label='Old equilibria')
plt.plot('xx', 'yy', data=dotted_two, linestyle='dotted', color='grey', label='', lw=3)

plt.scatter(x=2.25, y=2.875, zorder=2, color='royalblue', s=60, label='New equilibrium')
plt.plot('xx', 'yy', data=dotted_three, linestyle='dotted', color='royalblue', label='', lw=3)

# plot arrows
plt.arrow(0.5, 1.25, -0.15, 0.3, width=0.015, head_width=0.13, head_length=0.13, fc='k', ec='k')
plt.arrow(3.5, 2.75, -0.15, 0.3, width=0.015, head_width=0.13, head_length=0.13, fc='k', ec='k')

# axes labels
plt.xlabel('Quantity', fontsize=16)
plt.ylabel('Price', fontsize=16)

# axes limits
plt.xlim([-0.3, 4.3])
plt.ylim([-0.3, 4.3])

# title and legend
plt.title('Situation for Non-residents: Decrease in Supply', fontsize=16, pad=20)
plt.legend(bbox_to_anchor=(0.5, -0.4), loc=8, prop={'size': 13}, ncol=2)
plt.tight_layout()

# ----- SECOND SUBPLOT -----
plt.subplot(1, 2, 2)

# plot axes
plt.axvline(ymin=0.065, ymax=0.93, color='black')
plt.axhline(xmin=0.065, xmax=0.93, color='black')

# plot supply and demand curves
plt.plot('Quantity', 'Price', data=df_housing_supply_decrease, 
         label='Supply #2', color='tomato', zorder=1, linestyle='dashed', lw=2)

plt.plot('Quantity', 'Price', data=df_housing_demand_increase,
         label='Demand #2', color='lightseagreen', linestyle='dashed',
         zorder=1, lw=2)
plt.plot('Quantity', 'Price', data=df_housing_demand_increase2,
         label='Demand #3 (increase)', color='lightseagreen', zorder=1,
         linestyle='dashdot', lw=2)

# plot equilibria and plumb lines
plt.scatter(x=3, y=2.5, zorder=2, color='grey', s=60)

plt.scatter(x=2.25, y=2.875, zorder=2, color='grey', s=60, label='Old equilibria')
plt.plot('xx', 'yy', data=dotted_three, linestyle='dotted', color='grey', label='', lw=3)

plt.scatter(x=2.5, y=3, zorder=2, color='royalblue', s=60, label='New equilibrium')
plt.plot('xx', 'yy', data=dotted_four, linestyle='dotted', color='royalblue', label='', lw=3)

# plot arrows
plt.arrow(0.5, 3.75, 0.03, 0.07, width=0.015, head_width=0.13, head_length=0.13, fc='k', ec='k')
plt.arrow(3.5, 2.25, 0.03, 0.07, width=0.015, head_width=0.13, head_length=0.13, fc='k', ec='k')

# axes labels
plt.xlabel('Quantity', fontsize=16)
plt.ylabel('Price', fontsize=16)

# axes limits
plt.xlim([-0.3, 4.3])
plt.ylim([-0.3, 4.3])

# title and legend
plt.title('Response by All: Increase in Demand', fontsize=18, pad=20)
plt.legend(bbox_to_anchor=(0.5, -0.4), loc=8, prop={'size': 13}, ncol=2)
plt.tight_layout()

# ----- End of second subplot -----

# figure title
plt.subplots_adjust(top=0.83)
fig.suptitle('St. Ives Housing Market: Post-Legislation', fontsize=20)
fig.savefig('st-ives-housing-market-post-legislation.png', dpi=180);
In [19]:
# real data on St. Ives, from Financial Times
# numbers rounded to nearest thousand British pound
# https://www.ft.com/content/6abb85e8-c349-11e9-ae6e-a26d1d0455f4
df_dots_2016 = pd.DataFrame(np.array([[310,0], [310,323], [0,323]]), 
                          columns=['xx', 'yy'])

df_dots_2018 = pd.DataFrame(np.array([[270,0], [270,352], [0,352]]), 
                          columns=['xx', 'yy'])
In [20]:
# set figure size and style
fig = plt.figure(figsize=(12,8))
sns.set_style('darkgrid')

# ----- FIRST SUBPLOT ------
plt.subplot(1, 2, 1)

# plot axes
plt.axvline(ymin=0.065, ymax=0.93, color='black')
plt.axhline(xmin=0.065, xmax=0.93, color='black')

# plot supply and demand curves
plt.plot('Quantity', 'Price', data=df_housing_supply, color='tomato',
         zorder=1, lw=2, label='')

plt.plot('Quantity', 'Price', data=df_housing_demand_increase, 
         color='lightseagreen', linestyle='dashed', zorder=1, lw=2, label='')

plt.plot('Quantity', 'Price', data=df_housing_supply_decrease, color='tomato',
         zorder=1, linestyle='dashed', lw=2, label='')

plt.plot('Quantity', 'Price', data=df_housing_demand_increase2,
         color='lightseagreen', zorder=1, linestyle='dashdot', lw=2, label='')


# plot equilibria and plumb lines
plt.scatter(x=3, y=2.5, zorder=2, color='grey', s=60, label='Pre-legislation equilibrium')
plt.plot('xx', 'yy', data=dotted_two, linestyle='dotted', color='grey', 
         label='', lw=3)

plt.scatter(x=2.5, y=3, zorder=2, color='royalblue', s=60, label='Post-legislation equilibrium')
plt.plot('xx', 'yy', data=dotted_four, linestyle='dotted', 
         color='royalblue', label='', lw=3)

# axes labels
plt.xlabel('Quantity', fontsize=16)
plt.ylabel('Price', fontsize=16)

# axes limits
plt.xlim([-0.3, 4.3])
plt.ylim([-0.3, 4.3])

# title and legend
plt.title('Theory', fontsize=18, pad=20)
plt.legend(bbox_to_anchor=(0.5, -0.4), loc=8, prop={'size': 13})
plt.tight_layout()

# ----- SECOND SUBPLOT -----
plt.subplot(1, 2, 2)

# plot axes
plt.axvline(ymin=0.07, ymax=0.95, color='black')
plt.axhline(xmin=0.07, xmax=0.95, color='black')

# plot equilibria and plumb lines
plt.scatter(x=310, y=323, zorder=2, color='grey', s=60, label='2016 equilibrium, pre-legislation')
plt.plot('xx', 'yy', data=df_dots_2016, linestyle='dotted', color='grey', label='', lw=3)

plt.scatter(x=270, y=352, zorder=2, color='royalblue', s=60, label='2018 equilibrium, post-legislation')
plt.plot('xx', 'yy', data=df_dots_2018, linestyle='dotted', color='royalblue', label='', lw=3)

# axes labels
plt.xlabel('Quantity', fontsize=16)
plt.ylabel('Price in thousands of pounds', fontsize=16)

# axes limits
plt.xlim([-38, 500])
plt.ylim([-38, 500])

# title and legend
plt.title('Reality', fontsize=18, pad=20)
plt.legend(bbox_to_anchor=(0.5, -0.4), loc=8, prop={'size': 13})
plt.tight_layout()

# ----- End of second subplot -----

# figure title
plt.subplots_adjust(top=0.83)
fig.suptitle('St. Ives Housing Market: Before & After Legislation', fontsize=20)
fig.savefig('st-ives-housing-market-theoretical-and-real.png', dpi=180);
In [ ]: