diff --git a/lectures/_static/lecture_specific/long_run_growth/tooze_ch1_graph.png b/lectures/_static/lecture_specific/long_run_growth/tooze_ch1_graph.png index c36dce06..3b7421b1 100644 Binary files a/lectures/_static/lecture_specific/long_run_growth/tooze_ch1_graph.png and b/lectures/_static/lecture_specific/long_run_growth/tooze_ch1_graph.png differ diff --git a/lectures/long_run_growth.md b/lectures/long_run_growth.md index 8abbaecc..d9a5ef57 100644 --- a/lectures/long_run_growth.md +++ b/lectures/long_run_growth.md @@ -4,41 +4,40 @@ jupytext: extension: .md format_name: myst format_version: 0.13 - jupytext_version: 1.15.2 + jupytext_version: 1.16.1 kernelspec: display_name: Python 3 (ipykernel) language: python name: python3 --- - -# Economic Growth Evidence +# Long-Run Growth ## Overview -In this lecture we use Python, Pandas, and Matplotlib to download, organize, and visualize historical data on GDP growth. +In this lecture we use Python, {doc}`pandas`, and {doc}`Matplotlib` to download, organize, and visualize historical data on economic growth. -In addition to learning how to deploy these tools more generally, we'll use them to describe facts about economic growth experiences across many countries over several centuries. +In addition to learning how to deploy these tools more generally, we'll use them to describe facts about economic growth experiences across many countries over several centuries. -Such "growth facts" are interesting for a variety of reasons. +Such "growth facts" are interesting for a variety of reasons. -Explaining growth facts is a principal purpose of both "development economics" and "economic history". +Explaining growth facts is a principal purpose of both "development economics" and "economic history". -And growth facts are important inputs into historians' studies of geopolitical forces and dynamics. +And growth facts are important inputs into historians' studies of geopolitical forces and dynamics. -Thus, Adam Tooze's account of the geopolitical precedents and antecedents of World War I begins by describing how Gross National Products of European Great Powers had evolved during the 70 years preceding 1914 (see chapter 1 of {cite}`Tooze_2014`). +Thus, Adam Tooze's account of the geopolitical precedents and antecedents of World War I begins by describing how the Gross Domestic Products (GDP) of European Great Powers had evolved during the 70 years preceding 1914 (see chapter 1 of {cite}`Tooze_2014`). -Using the very same data that Tooze used to construct his figure, here is our version of his chapter 1 figure. +Using the very same data that Tooze used to construct his figure (with a slightly longer timeline), here is our version of his chapter 1 figure. ```{figure} _static/lecture_specific/long_run_growth/tooze_ch1_graph.png -:width: 75% +:width: 100% ``` -(This is just a copy of our figure {numref}`gdp1`. We desribe how we constructed it later in this lecture.) +(This is just a copy of our figure {numref}`gdp1`. We describe how we constructed it later in this lecture.) -Chapter 1 of {cite}`Tooze_2014` used his graph to show how US GDP started the 19th century way behind the GDP of the British Empire. +Chapter 1 of {cite}`Tooze_2014` used his graph to show how US GDP started the 19th century way behind the GDP of the British Empire. By the end of the nineteenth century, US GDP had caught up with GDP of the British Empire, and how during the first half of the 20th century, US GDP surpassed that of the British Empire. @@ -50,7 +49,7 @@ tempts one to want a counterpart to his graph for 2014 or later. (An impatient reader seeking a hint at the answer might now want to jump ahead and look at figure {numref}`gdp2`.) -As we'll see, reasoning by analogy, this graph perhaps set the stage for an "XXX (21st) century", where you are free to fill in your guess for country XXX. +As we'll see, reasoning by analogy, this graph perhaps set the stage for an "XXX (21st) century", where you are free to fill in your guess for country XXX. As we gather data to construct those two graphs, we'll also study growth experiences for a number of countries for time horizons extending as far back as possible. @@ -58,12 +57,12 @@ These graphs will portray how the "Industrial Revolution" began in Britain in th In a nutshell, this lecture records growth trajectories of various countries over long time periods. -While some countries have experienced long term rapid growth across that has lasted a hundred years, others have not. +While some countries have experienced long-term rapid growth across that has lasted a hundred years, others have not. Since populations differ across countries and vary within a country over time, it will be interesting to describe both total GDP and GDP per capita as it evolves within a country. -First let's import the packages needed to explore what the data says about long run growth +First let's import the packages needed to explore what the data says about long-run growth ```{code-cell} ipython3 import pandas as pd @@ -73,75 +72,71 @@ import numpy as np from collections import namedtuple ``` - ## Setting up A project initiated by [Angus Maddison](https://en.wikipedia.org/wiki/Angus_Maddison) has collected many historical time series related to economic growth, some dating back to the first century. -The data can be downloaded from the [Maddison Historical Statistics webpage](https://www.rug.nl/ggdc/historicaldevelopment/maddison/) by clicking on the "Latest Maddison Project Release". +The data can be downloaded from the [Maddison Historical Statistics](https://www.rug.nl/ggdc/historicaldevelopment/maddison/) by clicking on the "Latest Maddison Project Release". -For convenience, here is a copy of the {download}`2020 data ` in `Excel` format. +We are going to read the data from a QuantEcon GitHub repository. -Let's read it into a pandas dataframe: +Our objective in this section is to produce a convenient `DataFrame` instance that contains per capita GDP for different countries. + +Here we read the Maddison data into a pandas `DataFrame`: ```{code-cell} ipython3 -data = pd.read_excel("datasets/mpd2020.xlsx", sheet_name='Full data') -data +data_url = "https://github.com/QuantEcon/lecture-python-intro/raw/main/lectures/datasets/mpd2020.xlsx" +data = pd.read_excel(data_url, + sheet_name='Full data') +data.head() ``` - -We can see that this dataset contains GDP per capita (gdppc) and population (pop) for many countries and years. +We can see that this dataset contains GDP per capita (`gdppc`) and population (pop) for many countries and years. Let's look at how many and which countries are available in this dataset ```{code-cell} ipython3 -len(data.country.unique()) +countries = data.country.unique() +len(countries) ``` - We can now explore some of the 169 countries that are available. Let's loop over each country to understand which years are available for each country ```{code-cell} ipython3 -cntry_years = [] -for cntry in data.country.unique(): - cy_data = data[data.country == cntry]['year'] +country_years = [] +for country in countries: + cy_data = data[data.country == country]['year'] ymin, ymax = cy_data.min(), cy_data.max() - cntry_years.append((cntry, ymin, ymax)) -cntry_years = pd.DataFrame(cntry_years, - columns=['country', 'Min Year', 'Max Year']).set_index('country') -cntry_years + country_years.append((country, ymin, ymax)) +country_years = pd.DataFrame(country_years, + columns=['country', 'min_year', 'max_year']).set_index('country') +country_years.head() ``` - -Let's now reshape the original data into some convenient variables to enable quicker access to countries time series data. +Let's now reshape the original data into some convenient variables to enable quicker access to countries' time series data. We can build a useful mapping between country codes and country names in this dataset ```{code-cell} ipython3 -code_to_name = data[['countrycode', 'country']].drop_duplicates().reset_index(drop=True).set_index(['countrycode']) +code_to_name = data[ + ['countrycode', 'country']].drop_duplicates().reset_index(drop=True).set_index(['countrycode']) ``` - -Then we can quickly focus on GDP per capita (gdp) +Now we can focus on GDP per capita (`gdppc`) and generate a wide data format ```{code-cell} ipython3 -data +gdp_pc = data.set_index(['countrycode', 'year'])['gdppc'] +gdp_pc = gdp_pc.unstack('countrycode') ``` ```{code-cell} ipython3 -gdppc = data.set_index(['countrycode', 'year'])['gdppc'] -gdppc = gdppc.unstack('countrycode') -``` - -```{code-cell} ipython3 -gdppc +gdp_pc.tail() ``` - -We create a color mapping between country codes and colors for consistency +We create a variable `color_mapping` to store a map between country codes and colors for consistency ```{code-cell} ipython3 :tags: [hide-input] @@ -152,12 +147,17 @@ country_names = data['countrycode'] colors = cm.tab20(np.linspace(0, 0.95, len(country_names))) # Create a dictionary to map each country to its corresponding color -color_mapping = {country: color for country, color in zip(country_names, colors)} +color_mapping = {country: color for + country, color in zip(country_names, colors)} ``` -## GDP plots +## GDP per capita + +In this section we examine GDP per capita over the long run for several different countries. + +### United Kingdom -Looking at the United Kingdom we can first confirm we are using the correct country code +First we examine UK GDP growth ```{code-cell} ipython3 --- @@ -168,19 +168,17 @@ mystnb: width: 500px --- fig, ax = plt.subplots(dpi=300) -cntry = 'GBR' -_ = gdppc[cntry].plot( - ax=fig.gca(), - ylabel='International $\'s', - xlabel='Year', - linestyle='-', - color=color_mapping['GBR'] - ) +country = 'GBR' +gdp_pc[country].plot( + ax=ax, + ylabel='international dollars', + xlabel='year', + color=color_mapping[country] + ); ``` - :::{note} -[International Dollars](https://en.wikipedia.org/wiki/International_dollar) are a hypothetical unit of currency that has the same purchasing power parity that the U.S. Dollar has in the United States at any given time. They are also known as Geary–Khamis dollars (GK Dollars). +[International dollars](https://en.wikipedia.org/wiki/international_dollar) are a hypothetical unit of currency that has the same purchasing power parity that the U.S. Dollar has in the United States at a given point in time. They are also known as Geary–Khamis dollars (GK Dollars). ::: We can see that the data is non-continuous for longer periods in the early 250 years of this millennium, so we could choose to interpolate to get a continuous line plot. @@ -195,28 +193,39 @@ mystnb: name: gdppc_gbr2 --- fig, ax = plt.subplots(dpi=300) -cntry = 'GBR' -ax.plot(gdppc[cntry].interpolate(), +country = 'GBR' +ax.plot(gdp_pc[country].interpolate(), linestyle='--', lw=2, - color=color_mapping[cntry]) + color=color_mapping[country]) -ax.plot(gdppc[cntry], - linestyle='-', +ax.plot(gdp_pc[country], lw=2, - color=color_mapping[cntry]) -ax.set_ylabel('International $\'s') -ax.set_xlabel('Year') + color=color_mapping[country]) +ax.set_ylabel('international dollars') +ax.set_xlabel('year') plt.show() ``` +### Comparing the US, UK, and China -We can now put this into a function to generate plots for a list of countries +In this section we will compare GDP growth for the US, UK and China. -```{code-cell} ipython3 -def draw_interp_plots(series, ylabel, xlabel, color_mapping, code_to_name, lw, logscale, ax): +As a first step we create a function to generate plots for a list of countries - for i, c in enumerate(cntry): +```{code-cell} ipython3 +def draw_interp_plots(series, # pandas series + country, # list of country codes + ylabel, # label for y-axis + xlabel, # label for x-axis + color_mapping, # code-color mapping + code_to_name, # code-name mapping + lw, # line width + logscale, # log scale for y-axis + ax # matplolib axis + ): + + for c in country: # Get the interpolated data df_interpolated = series[c].interpolate(limit_area='inside') interpolated_data = df_interpolated[series[c].isnull()] @@ -230,24 +239,20 @@ def draw_interp_plots(series, ylabel, xlabel, color_mapping, code_to_name, lw, l # Plot the non-interpolated data with solid lines ax.plot(series[c], - linestyle='-', lw=lw, color=color_mapping[c], alpha=0.8, label=code_to_name.loc[c]['country']) - if logscale == True: + if logscale: ax.set_yscale('log') # Draw the legend outside the plot - ax.legend(loc='center left', bbox_to_anchor=(1, 0.5), frameon=False) + ax.legend(loc='upper left', frameon=False) ax.set_ylabel(ylabel) ax.set_xlabel(xlabel) - - return ax ``` - As you can see from this chart, economic growth started in earnest in the 18th century and continued for the next two hundred years. How does this compare with other countries' growth trajectories? @@ -267,10 +272,11 @@ Event = namedtuple('Event', ['year_range', 'y_text', 'text', 'color', 'ymax']) fig, ax = plt.subplots(dpi=300, figsize=(10, 6)) -cntry = ['CHN', 'GBR', 'USA'] -ax = draw_interp_plots(gdppc[cntry].loc[1500:], - 'International $\'s','Year', - color_mapping, code_to_name, 2, False, ax) +country = ['CHN', 'GBR', 'USA'] +draw_interp_plots(gdp_pc[country].loc[1500:], + country, + 'international dollars','year', + color_mapping, code_to_name, 2, False, ax) # Define the parameters for the events and the text ylim = ax.get_ylim()[1] @@ -312,22 +318,22 @@ def draw_events(events, ax): color=event.color, **t_params) ax.axvspan(*event.year_range, color=event.color, alpha=0.2) ax.axvline(event_mid, ymin=1, ymax=event.ymax, color=event.color, - linestyle='-', clip_on=False, alpha=0.15) + clip_on=False, alpha=0.15) # Draw events draw_events(events, ax) plt.show() ``` - -The preceding graph of per capita GDP strikingly reveals how the spread of the industrial revolution has over time gradually lifted the living standards of substantial +The preceding graph of per capita GDP strikingly reveals how the spread of the Industrial Revolution has over time gradually lifted the living standards of substantial groups of people -- most of the growth happened in the past 150 years after the industrial revolution. +- most of the growth happened in the past 150 years after the Industrial Revolution. - per capita GDP in the US and UK rose and diverged from that of China from 1820 to 1940. - the gap has closed rapidly after 1950 and especially after the late 1970s. - these outcomes reflect complicated combinations of technological and economic-policy factors that students of economic growth try to understand and quantify. +### Focusing on China It is fascinating to see China's GDP per capita levels from 1500 through to the 1970s. @@ -350,10 +356,11 @@ tags: [hide-input] --- fig, ax = plt.subplots(dpi=300, figsize=(10, 6)) -cntry = ['CHN'] -ax = draw_interp_plots(gdppc[cntry].loc[1600:2000], - 'International $\'s','Year', - color_mapping, code_to_name, 2, True, ax) +country = ['CHN'] +draw_interp_plots(gdp_pc[country].loc[1600:2000], + country, + 'international dollars','year', + color_mapping, code_to_name, 2, True, ax) ylim = ax.get_ylim()[1] @@ -389,12 +396,13 @@ draw_events(events, ax) plt.show() ``` +### Focusing on the US and UK -We can also look at the United States (USA) and United Kingdom (GBR) in more detail +Now we look at the United States (USA) and United Kingdom (GBR) in more detail. In the following graph, please watch for - impact of trade policy (Navigation Act). -- productivity changes brought by the industrial revolution. +- productivity changes brought by the Industrial Revolution. - how the US gradually approaches and then surpasses the UK, setting the stage for the ''American Century''. - the often unanticipated consequences of wars. - interruptions and scars left by [business cycle](business_cycle) recessions and depressions. @@ -409,14 +417,15 @@ tags: [hide-input] --- fig, ax = plt.subplots(dpi=300, figsize=(10, 6)) -cntry = ['GBR', 'USA'] -ax = draw_interp_plots(gdppc[cntry].loc[1500:2000], - 'International $\'s','Year', - color_mapping, code_to_name, 2, True, ax) +country = ['GBR', 'USA'] +draw_interp_plots(gdp_pc[country].loc[1500:2000], + country, + 'international dollars','year', + color_mapping, code_to_name, 2, True, ax) ylim = ax.get_ylim()[1] -# Create a list of data points= +# Create a list of data points events = [ Event((1651, 1651), ylim + ylim*0.15, 'Navigation Act (UK)\n(1651)', @@ -449,21 +458,19 @@ draw_events(events, ax) plt.show() ``` - -## The industrialized world +## GDP growth Now we'll construct some graphs of interest to geopolitical historians like Adam Tooze. We'll focus on total Gross Domestic Product (GDP) (as a proxy for ''national geopolitical-military power'') rather than focusing on GDP per capita (as a proxy for living standards). ```{code-cell} ipython3 -data = pd.read_excel("datasets/mpd2020.xlsx", sheet_name='Full data') +data = pd.read_excel(data_url, sheet_name='Full data') data.set_index(['countrycode', 'year'], inplace=True) data['gdp'] = data['gdppc'] * data['pop'] gdp = data['gdp'].unstack('countrycode') ``` - ### Early industrialization (1820 to 1940) We first visualize the trend of China, the Former Soviet Union, Japan, the UK and the US. @@ -482,17 +489,17 @@ mystnb: name: gdp1 --- fig, ax = plt.subplots(dpi=300) -ax = fig.gca() -cntry = ['CHN', 'SUN', 'JPN', 'GBR', 'USA'] +country = ['CHN', 'SUN', 'JPN', 'GBR', 'USA'] start_year, end_year = (1820, 1945) -ax = draw_interp_plots(gdp[cntry].loc[start_year:end_year], - 'International $\'s', 'Year', - color_mapping, code_to_name, 2, False, ax) +draw_interp_plots(gdp[country].loc[start_year:end_year], + country, + 'international dollars', 'year', + color_mapping, code_to_name, 2, False, ax) ``` +#### Constructing a plot similar to Tooze's -## Constructing a plot similar to Tooze's -In this section we describe how we have constructed a version of the striking figure from chapter 1 of {cite}`Tooze_2014` that we discussed at the start of this lecture. +In this section we describe how we have constructed a version of the striking figure from chapter 1 of {cite}`Tooze_2014` that we discussed at the start of this lecture. Let's first define a collection of countries that consist of the British Empire (BEM) so we can replicate that series in Tooze's chart. @@ -502,20 +509,6 @@ BEM = ['GBR', 'IND', 'AUS', 'NZL', 'CAN', 'ZAF'] gdp['BEM'] = gdp[BEM].loc[start_year-1:end_year].interpolate(method='index').sum(axis=1) ``` - -Let's take a look at the aggregation that represents the British Empire. - -```{code-cell} ipython3 -# The first year is np.nan due to interpolation -gdp['BEM'].plot(ylabel="International $'s") -plt.show() -``` - -```{code-cell} ipython3 -code_to_name -``` - - Now let's assemble our series and get ready to plot them. ```{code-cell} ipython3 @@ -529,19 +522,18 @@ code_to_name = pd.concat([code_to_name, bem]) ```{code-cell} ipython3 fig, ax = plt.subplots(dpi=300) -ax = fig.gca() -cntry = ['DEU', 'USA', 'SUN', 'BEM', 'FRA', 'JPN'] +country = ['DEU', 'USA', 'SUN', 'BEM', 'FRA', 'JPN'] start_year, end_year = (1821, 1945) -ax = draw_interp_plots(gdp[cntry].loc[start_year:end_year], - 'Real GDP in 2011 $\'s', 'Year', - color_mapping, code_to_name, 2, False, ax) +draw_interp_plots(gdp[country].loc[start_year:end_year], + country, + 'international dollars', 'year', + color_mapping, code_to_name, 2, False, ax) plt.savefig("./_static/lecture_specific/long_run_growth/tooze_ch1_graph.png", dpi=300, bbox_inches='tight') plt.show() ``` - At the start of this lecture, we noted how US GDP came from "nowhere" at the start of the 19th century to rival and then overtake the GDP of the British Empire by the end of the 19th century, setting the geopolitical stage for the "American (twentieth) century". @@ -561,71 +553,46 @@ mystnb: name: gdp2 --- fig, ax = plt.subplots(dpi=300) -ax = fig.gca() -cntry = ['CHN', 'SUN', 'JPN', 'GBR', 'USA'] +country = ['CHN', 'SUN', 'JPN', 'GBR', 'USA'] start_year, end_year = (1950, 2020) -ax = draw_interp_plots(gdp[cntry].loc[start_year:end_year], - 'International $\'s', 'Year', - color_mapping, code_to_name, 2, False, ax) +draw_interp_plots(gdp[country].loc[start_year:end_year], + country, + 'international dollars', 'year', + color_mapping, code_to_name, 2, False, ax) ``` - -It is tempting to compare this graph with figure {numref}`gdp1` that showed the US overtaking the UK near the start of the "American Century", a version of the graph featured in chapter 1 of {cite}`Tooze_2014`. +It is tempting to compare this graph with figure {numref}`gdp1` that showed the US overtaking the UK near the start of the "American Century", a version of the graph featured in chapter 1 of {cite}`Tooze_2014`. ## Regional analysis -We often want to study historical experiences of countries outside the club of "World Powers". +We often want to study the historical experiences of countries outside the club of "World Powers". -Fortunately, the [Maddison Historical Statistics](https://www.rug.nl/ggdc/historicaldevelopment/maddison/) dataset also includes regional aggregations +The [Maddison Historical Statistics](https://www.rug.nl/ggdc/historicaldevelopment/maddison/) dataset also includes regional aggregations ```{code-cell} ipython3 -data = pd.read_excel("datasets/mpd2020.xlsx", sheet_name='Regional data', header=(0,1,2), +data = pd.read_excel(data_url, + sheet_name='Regional data', + header=(0,1,2), index_col=0) data.columns = data.columns.droplevel(level=2) ``` - We can save the raw data in a more convenient format to build a single table of regional GDP per capita ```{code-cell} ipython3 -regionalgdppc = data['gdppc_2011'].copy() -regionalgdppc.index = pd.to_datetime(regionalgdppc.index, format='%Y') +regionalgdp_pc = data['gdppc_2011'].copy() +regionalgdp_pc.index = pd.to_datetime(regionalgdp_pc.index, format='%Y') ``` - Let's interpolate based on time to fill in any gaps in the dataset for the purpose of plotting ```{code-cell} ipython3 -regionalgdppc.interpolate(method='time', inplace=True) -``` - - -and record a dataset of world GDP per capita - -```{code-cell} ipython3 -worldgdppc = regionalgdppc['World GDP pc'] -``` - -```{code-cell} ipython3 ---- -mystnb: - figure: - caption: World GDP per capita - name: world_gdppc ---- -fig = plt.figure(dpi=300) -ax = fig.gca() -ax = worldgdppc.plot( - ax=ax, - xlabel='Year', - ylabel='2011 US$', -) +regionalgdp_pc.interpolate(method='time', inplace=True) ``` +Looking more closely, let's compare the time series for `Western Offshoots` and `Sub-Saharan Africa` with a number of different regions around the world. -Looking more closely, let's compare the time series for `Western Offshoots` and `Sub-Saharan Africa` and more broadly at a number of different regions around the world. - -Again we see the divergence of the West from the rest of the world after the industrial revolution and the convergence of the world after the 1950s +Again we see the divergence of the West from the rest of the world after the Industrial Revolution and the convergence of the world after the 1950s ```{code-cell} ipython3 --- @@ -634,13 +601,12 @@ mystnb: caption: Regional GDP per capita name: region_gdppc --- -fig = plt.figure(dpi=300) -ax = fig.gca() -line_styles = ['-', '--', ':', '-.', '.', 'o', '-', '--', '-'] -ax = regionalgdppc.plot(ax=ax, xlabel='Year', - ylabel='2011 US$', style=line_styles) +fig, ax = plt.subplots(dpi=300) +regionalgdp_pc.plot(ax=ax, xlabel='year', + lw=2, + ylabel='international dollars') ax.set_yscale('log') plt.legend(loc='lower center', - ncol=3, bbox_to_anchor=[0.5, -0.4]) + ncol=3, bbox_to_anchor=[0.5, -0.5]) plt.show() ```