library(readxl)
library(dplyr)
library(tidyr)
library(here)
library(systemfonts)
library(ragg)
library(textshaping)
source(here("utils/theme_and_colors_IMF_base_R.R"))
source(here("utils/Add_text_to_figure_panel_base_R.R"))
Panel charts with text annotation
Introduction
In this section we will show how to make panel charts with text annotation–the narrative on top of a individual panel charts that you often see in IMF staff reports.
Panel charts of Jamaica’s public finances
This tutorial will guide you through the process of creating panel charts of the public finances of Jamaica. This chart has appeared in the 2022 Jamaica staff report.
Setup
First, we load the required R libraries and source the custom functions that we will use throughout this tutorial.
Reading the Data
The data for our charts is stored across multiple sheets within an Excel workbook. We’ll read each sheet into its own R object.
<- read_excel(here("databases/SR charts v1.xlsx"), sheet = "Chart 1 Data")
chart_1_data <- read_excel(here("databases/SR charts v1.xlsx"), sheet = "Chart 2 Data")
chart_2_data <- read_excel(here("databases/SR charts v1.xlsx"), sheet = "Chart 3 Data")
chart_3_data <- read_excel(here("databases/SR charts v1.xlsx"), sheet = "Chart 4 Data")
chart_4_data <- read_excel(here("databases/SR charts v1.xlsx"), sheet = "Chart 5 Data")
chart_5_data <- read_excel(here("databases/SR charts v1.xlsx"), sheet = "Chart 6 Data") chart_6_data
Data Transformation
The data is in a format that is common in IMF spreadsheets:
head(chart_2_data)
# A tibble: 2 × 12
Year `2010` `2011` `2012` `2013` `2014` `2015` `2016` `2017` `2018` `2019`
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Total R… 26.8 25.6 25.7 27.1 26.2 27.0 28.0 29.1 30.6 30.6
2 Total E… 33.2 32.0 29.8 27.0 26.7 27.3 28.2 28.6 29.4 29.7
# ℹ 1 more variable: `2020` <dbl>
We need to transform our data into a long format that is suitable for plotting. We’ll define a function make_long
for this purpose and apply it to our datasets.
<- function(data) {
make_long <- data %>%
data_long rename(label = Year) %>%
pivot_longer(-label, names_to = "year", values_to = "value") %>%
mutate(year = as.numeric(year))
<- data_long %>%
data_long pivot_wider(names_from = label, values_from = value)
return(data_long)
}
Let’s use this on one file and see the results;
<- make_long(chart_2_data)
data_2_long head(data_2_long)
# A tibble: 6 × 3
year `Total Revenue` `Total Expenditure`
<dbl> <dbl> <dbl>
1 2010 26.8 33.2
2 2011 25.6 32.0
3 2012 25.7 29.8
4 2013 27.1 27.0
5 2014 26.2 26.7
6 2015 27.0 27.3
Now do all data sets:
<- make_long(chart_1_data)
data_1_long <- make_long(chart_2_data)
data_2_long <- make_long(chart_3_data)
data_3_long <- make_long(chart_4_data)
data_4_long <- make_long(chart_5_data)
data_5_long <- make_long(chart_6_data) data_6_long
Creating the Plots
With our data in the correct format, we can now create our visualizations using base R.
Let’s first set up the chart theme. We have written functions for you, so all you need to do is to call it before plotting. set_theme
is a function that sets the graphical parameters according to the set_imf_theme
function.
Optionally, if you want to reset the default settings of R charts, simply run par("default")
.
<- set_imf_theme(primary_font, blue)
set_theme set_theme()
We then use base R to plot the charts.
Please notice that we created a separate function add_titles(title, subtitle)
to add customized titles and subtitles to each plot to keep the overall IMF format consistent.
<- function() {
fig_chart_1_fiscal set_theme()
barplot(data_1_long$`Fiscal Balance`,
names.arg = data_1_long$year,
beside = TRUE,
col = blue,
border = "black",
width = 0.2,
space = 1,
ylim = c(-8, 2)
)add_titles("Central Government Balance", "(In percent of GDP)")
box(lwd = 0.5)
}
fig_chart_1_fiscal()
<- function() {
fig_chart_2_fiscal set_theme()
plot(data_2_long$year, data_2_long$`Total Revenue`, type = "l",
xlim = c(2010, 2020), ylim = c(24, 34), col=blue,lwd=4,
xlab = "", ylab = "")
add_titles("Central Government Revenues and Expenditures",
"(In percent of GDP)")
lines(data_2_long$year, data_2_long$`Total Expenditure`,
col = green, lty = "dashed", lwd = 4)
legend("topright", inset = c(0.02, 0.02),
legend = c("Revenue","Expenditure"),
col = c(blue, green),
lty = c("solid", "dashed"), lwd = 4, bty = "n", cex = 10/12)
axis(1, at = seq(2010, 2020, 1), labels = seq(2010, 2020, 1))
axis(2, at = seq(24, 34, 2), labels = seq(24, 34, 2))
box(lwd = 0.5)
}
fig_chart_2_fiscal()
<- function() {
fig_chart_3_fiscal set_theme()
<- t((as.matrix(data_3_long[,c(3,4)])))
df_matrix colnames(df_matrix) <- data_3_long$year
barplot((df_matrix), beside = FALSE, col = c(green, blue),
border = "black",
space = 1, ylim = c(0, 30))
legend("top", legend = rownames(df_matrix), fill = c(green, blue),
bty = "n", ncol = 2, cex = 10/12)
add_titles("Tax Revenue", "(In percent of GDP)")
box(lwd = 0.5)
}
fig_chart_3_fiscal()
<- function() {
fig_chart_4_fiscal set_theme()
<- t((as.matrix(data_4_long[,c(3,4)])))
df_matrix colnames(df_matrix) <- data_4_long$year
barplot(df_matrix, beside = FALSE, col = c(green, blue), border = "black",
space = 1, ylim = c(0, 35))
legend("top", legend = rownames(df_matrix), fill = c(green, blue), bty = "n",
ncol = 1, cex = 10/12)
add_titles("Central Government Current Spending", "(In percent of GDP)")
box(lwd = 0.5)
}
fig_chart_4_fiscal()
<- function() {
fig_chart_5_fiscal set_theme()
barplot(data_5_long$`Capital Spending`, names.arg = data_5_long$year, col = blue,
border = "black", space = 1, ylim = c(0, 5))
add_titles("Central Government Capital Spending", "(In percent of GDP)")
box(lwd = 0.5)
}
fig_chart_5_fiscal()
<- function() {
fig_chart_6_fiscal set_theme()
<- barplot(data_6_long$`Debt (Rhs)`, names.arg = data_6_long$year,
bp col = green, border = "black", space = 1, ylim = c(0, 140))
add_titles("Primary Balance and Public Debt", "(In percent of GDP)")
# data_for_lines <- chart_6_fiscal_long[chart_6_fiscal_long$label != "Debt (Rhs)", ]
par(new = TRUE)
plot(data_6_long$year, data_6_long$`Primary Balance (Lhs)`, type = "l",
col = blue, lwd = 4, xaxt = "n", yaxt = "n", xlab = "",
ylab = "", ylim = c(0, 8))
axis(side = 4)
legend("topright", legend = c("Public Debt", "Primary Balance(RHS)"),
fill = c(green, blue), border = "black", bty = "n", cex = 10/12)
box(lwd = 0.5)
}
fig_chart_6_fiscal()
Adding captions, combining, and saving charts
Once all individual plots are created, we can combine them into a single figure layout and save it as a .png file.
This step is much simpler in base R than using ggplot. We set up the file to save and the plot grid first, and then plot each of the six charts with proper captions into the grid and the file. After finishing, don’t forget to close the PNG file with dev.off()
.
# Open a PNG file with specified resolution, width, height, and units.
png("Figures/panel-figure-2-fiscal-baseR.png", res = 600, width = 12.51, height = 15.64, units = "in")
par(oma = c(3, 0, 3, 0), # Outer margins around the entire figure
mfrow = c(3, 2)) # Set up a 2x3 plot grid as the panel layout
<-
fig_chart_1_fiscal_text "The COVID-19 shock led to a sharp increase in central government's \nfiscal deficit and debt levels..."
<- AddTextToFigure(fig_chart_1_fiscal,fig_chart_1_fiscal_text)
fig_chart_1_fiscal_panel
<-
fig_chart_2_fiscal_text "...the revenue-to-GDP ratio declined and the expenditure-to-GDP \nratio increased."
<- AddTextToFigure(fig_chart_2_fiscal,fig_chart_2_fiscal_text)
fig_chart_2_fiscal_panel
<-
fig_chart_3_fiscal_text "Lower tax revenues in FY 2020 were the result of a decline in GDP and GCT\ntax cuts."
<- AddTextToFigure(fig_chart_3_fiscal,fig_chart_3_fiscal_text)
fig_chart_3_fiscal_panel
<-
fig_chart_4_fiscal_text "The increase in the spending ratio was largely the result of the decline in \nGDP."
<- AddTextToFigure(fig_chart_4_fiscal,fig_chart_4_fiscal_text)
fig_chart_4_fiscal_panel
<-
fig_chart_5_fiscal_text "While capital spending was held back to make room for COVID-19 \nrelated spending..."
<- AddTextToFigure(fig_chart_5_fiscal,fig_chart_5_fiscal_text)
fig_chart_5_fiscal_panel
<-
fig_chart_6_fiscal_text "...public debt rose in FY 2020 but is on a downward path to meet the FRL \ntarget."
<- AddTextToFigure(fig_chart_6_fiscal,fig_chart_6_fiscal_text)
fig_chart_6_fiscal_panel
title("Figure 7. Fiscal Sector Developments", outer = TRUE, line = 1.8,
cex.main = 1.5, font = 2, adj = 0.5)
mtext("Sources: Bank of Jamaica and IMF staff estimates and projections.",
side = 1, outer = TRUE, line = 0, cex = 1, adj = 0.05)
invisible(dev.off())
Conclusion
In this tutorial, we have covered the steps to import, process, and visualize fiscal data in base R. The resulting visualizations provide a compelling graphical representation of fiscal trends and developments.