We first clear the workspace using rm(list = ls())and
then include all packages we need. If a package is missing in your R
distribution (which is quite likely initially), just use
install.packages("package_name") with the respective
package name to install it on your system. If you execute the code in
the file install_packages.R, then all necessary packages
will be installed into your R distribution. If the variable
export_graphs is set to TRUE, then the graphs
will be exported as pdf-files. In addition, we define a set of colors
here to make graphs look more beautiful.
rm(list = ls())
library(reshape2)
library(base)
library(ggplot2)
library(grid)
library(scales)
library(stringr)
library(tidyverse)
library(pwt10)
# should graphs be exported to pdf
export_pdf <- FALSE
# define some colors
mygreen <- "#00BA38"
myblue <- "#619CFF"
myred <- "#F8766D"
We again use the Penn World Tables in pwt10.0 and
extract a sub-dataset that only contains US data.
data("pwt10.01")
pwt_sub <- subset(pwt10.01, isocode=="USA")
With these data at hand, we will study the five Kaldor Facts
regarding economic growth.
To establish this fact, we first calculate GDP (or output) per worker in the US economy. In fact, we take the \(log\) of GDP, as this allows us to study the growth properties of a variable (see our discussion in the lecture). We then regress output per worker on a constant as well as a linear time trend.
# calculate log-Output-per-Worker
pwt_sub$output_per_worker <- log(pwt_sub$rgdpe/pwt_sub$emp)
# run a linear regression
reg <- lm(output_per_worker ~ year, pwt_sub)
summary(reg)
##
## Call:
## lm(formula = output_per_worker ~ year, data = pwt_sub)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.08511 -0.02928 -0.01235 0.02778 0.08561
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -22.309186 0.480306 -46.45 <2e-16 ***
## year 0.016905 0.000242 69.85 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.04091 on 68 degrees of freedom
## Multiple R-squared: 0.9863, Adjusted R-squared: 0.9861
## F-statistic: 4879 on 1 and 68 DF, p-value: < 2.2e-16
The regression results show that a linear model provides quite
a good fit to our data. In fact, GDP per worker grows at approximately
1.7 percent per year in the period we are looking at. The model’s \(R^2\) value is 0.9862, meaning that we can
explain most of the variance of GDP over this time span by a linear
trend (the rest being the result mostly of cyclical fluctuations). The
following graph supports this view.
# for graph dimensions and annotation
xrng <- range(pwt_sub$year)
yrng <- range(pwt_sub$output_per_worker)
ymin <- (yrng[1]+yrng[2])/2 - 0.018*(xrng[2]-xrng[1])/2
ymax <- (yrng[1]+yrng[2])/2 + 0.018*(xrng[2]-xrng[1])/2
lab <- paste("growth rate = ", format(round(reg$coefficients[2]*100, 2), nsmall=2), "% / R2 = ", format(round(summary(reg)$r.squared, 2), nsmall=2))
# generate plot
myplot <- ggplot(data = pwt_sub) +
geom_line(aes(x=year, y=output_per_worker), color="darkblue", linewidth=1) +
geom_smooth(aes(x=year, y=output_per_worker), method="lm", formula="y ~ x", se=FALSE, color=myred) +
geom_label(aes(x = xrng[1], y = ymax, label = lab),
hjust = 0, vjust = 1, label.r = unit(0, "lines"), label.padding = unit(0.35, "lines")) +
coord_cartesian(xlim=c(1950, 2020), ylim=c(ymin, ymax)) +
scale_x_continuous(breaks=seq(1950, 2020, 10)) +
labs(x = "Year t",
y = "Log(Output/Worker)") +
theme_bw()
# print the plot
print(myplot)
## Warning in geom_label(aes(x = xrng[1], y = ymax, label = lab), hjust = 0, : All aesthetics have length 1, but the data has 70 rows.
## ℹ Please consider using `annotate()` or provide this layer with data containing
## a single row.
Note that the above graph is designed such that the y-axis
range covers as span of \(0.018 \cdot (2019 -
1950)\) log-points (1.8 percent growth per year) and that the
presented series is centered on the y-axis. Our 1.7 percent GDP per
worker growth series therefore perfectly fits this graph.
We can again calculate capital per worker and run a linear regression.
# calculate capital per worker
pwt_sub$capital_per_worker <- log(pwt_sub$rnna/pwt_sub$emp)
# run a linear regression
reg <- lm(capital_per_worker ~ year, pwt_sub)
summary(reg)
##
## Call:
## lm(formula = capital_per_worker ~ year, data = pwt_sub)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.096496 -0.018942 0.006438 0.029697 0.069123
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -1.482e+01 4.573e-01 -32.40 <2e-16 ***
## year 1.381e-02 2.304e-04 59.93 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.03895 on 68 degrees of freedom
## Multiple R-squared: 0.9814, Adjusted R-squared: 0.9811
## F-statistic: 3592 on 1 and 68 DF, p-value: < 2.2e-16
Capital per worker grows less than GDP per worker (only about
1.38 percent per year), but the \(R^2\)
value is very high as well. The following graph visualizes this.
# for graph dimensions and annotation
xrng <- range(pwt_sub$year)
yrng <- range(pwt_sub$capital_per_worker)
ymin <- (yrng[1]+yrng[2])/2 - 0.018*(xrng[2]-xrng[1])/2
ymax <- (yrng[1]+yrng[2])/2 + 0.018*(xrng[2]-xrng[1])/2
lab <- paste("growth rate = ", format(round(reg$coefficients[2]*100, 2), nsmall=2), "% / R2 = ", format(round(summary(reg)$r.squared, 2), nsmall=2))
# generate plot
myplot <- ggplot(data = pwt_sub) +
geom_line(aes(x=year, y=capital_per_worker), color="darkblue", linewidth=1) +
geom_smooth(aes(x=year, y=capital_per_worker), method="lm", formula="y ~ x", se=FALSE, color=myred) +
geom_label(aes(x = xrng[1], y = ymax, label = lab),
hjust = 0, vjust = 1, label.r = unit(0, "lines"), label.padding = unit(0.35, "lines")) +
coord_cartesian(xlim=c(1950, 2020), ylim=c(ymin, ymax)) +
scale_x_continuous(breaks=seq(1950, 2020, 10)) +
labs(x = "Year t",
y = "Log(Capital/Worker)") +
theme_bw()
# print the plot
print(myplot)
## Warning in geom_label(aes(x = xrng[1], y = ymax, label = lab), hjust = 0, : All aesthetics have length 1, but the data has 70 rows.
## ℹ Please consider using `annotate()` or provide this layer with data containing
## a single row.
The gross return on capital is defined as the amount of capital
compensation divided by the capital stock. It hence includes both the
net return on capital (in the PWT named irr) as well as the
capital decpreciation rate delta. As we can see in the
graph below, the gross return on capital is roughly constant over time
and ranges at around 11 to 12 percent.
# calculate gross rate of return on capital
pwt_sub$gross_return <- pwt_sub$irr + pwt_sub$delta
# for annotating
xrng <- range(pwt_sub$year)
yrng <- range(pwt_sub$gross_return)
ymin <- 0.06
ymax <- 0.17
lab <- paste("Long-run Level = ", format(round(mean(pwt_sub$gross_return), 3), nsmall=3))
myplot <- ggplot(data = pwt_sub) +
geom_line(aes(x=year, y=gross_return), color="darkblue", linewidth=1) +
geom_smooth(aes(x=year, y=gross_return), method="lm", formula="y ~ 1", se=FALSE, color=myred) +
geom_label(aes(x = xrng[2], y = ymax, label = lab),
hjust = 1, vjust = 1, label.r = unit(0, "lines"), label.padding = unit(0.35, "lines")) +
coord_cartesian(xlim=c(1950, 2020), ylim=c(ymin, ymax)) +
scale_x_continuous(breaks=seq(1950, 2020, 10)) +
labs(x = "Year t",
y = "Gross Return on Capital") +
theme_bw()
# print the plot
print(myplot)
## Warning in geom_label(aes(x = xrng[2], y = ymax, label = lab), hjust = 1, : All aesthetics have length 1, but the data has 70 rows.
## ℹ Please consider using `annotate()` or provide this layer with data containing
## a single row.
We can calculate the capital-to-output ratio (again in logs) and study its properties.
# calculate capital-to-output ratio
pwt_sub$capital_to_output <- log(pwt_sub$rnna/pwt_sub$rgdpna)
# run a linear regression
reg <- lm(capital_to_output ~ year, pwt_sub)
summary(reg)
##
## Call:
## lm(formula = capital_to_output ~ year, data = pwt_sub)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.043863 -0.023170 0.001303 0.015510 0.075039
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 7.2023489 0.2932969 24.56 <2e-16 ***
## year -0.0029546 0.0001478 -19.99 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.02498 on 68 degrees of freedom
## Multiple R-squared: 0.8546, Adjusted R-squared: 0.8525
## F-statistic: 399.7 on 1 and 68 DF, p-value: < 2.2e-16
The capital to output ratio is not exactly constant over time,
but its (negative) growth rate is much, much smaller than any of the
growth rates above. Note that the definition of the capital stock we use
here plays a role in the capital-to-output-ratio dynamics. If we were to
use only corporate capital from the NIPA accounts, we would get a more
constant picture. This can be seen for example in Herrendorf,
Rogerson, Valentinyi: Growth and the Kaldor Facts. The graph below
also shows that capital doesn’t move much over the time span
considered.
# for graph dimensions
xrng <- range(pwt_sub$year)
yrng <- range(pwt_sub$capital_to_output)
ymin <- (yrng[1]+yrng[2])/2 - 0.018*(xrng[2]-xrng[1])/2
ymax <- (yrng[1]+yrng[2])/2 + 0.018*(xrng[2]-xrng[1])/2
lab <- paste("growth rate = ", format(round(reg$coefficients[2]*100, 2), nsmall=2), "% / R2 = ", format(round(summary(reg)$r.squared, 2), nsmall=2))
# generate plot
myplot <- ggplot(data = pwt_sub) +
geom_line(aes(x=year, y=capital_to_output), color="darkblue", linewidth=1) +
geom_smooth(aes(x=year, y=capital_to_output), method="lm", formula="y ~ x", se=FALSE, color=myred) +
geom_label(aes(x = xrng[1], y = ymax, label = lab),
hjust = 0, vjust = 1, label.r = unit(0, "lines"), label.padding = unit(0.35, "lines")) +
coord_cartesian(xlim=c(1950, 2020), ylim=c(ymin, ymax)) +
scale_x_continuous(breaks=seq(1950, 2020, 10)) +
labs(x = "Year t",
y = "Log(Capital/Output)") +
theme_bw()
# print the plot
print(myplot)
## Warning in geom_label(aes(x = xrng[1], y = ymax, label = lab), hjust = 0, : All aesthetics have length 1, but the data has 70 rows.
## ℹ Please consider using `annotate()` or provide this layer with data containing
## a single row.