library(readxl)
library(dplyr)
library(tidyr)
library(ggpubr)
library(here)
library(gridExtra)
library(patchwork)
library(ragg)
source(here("utils/theme_and_colors_IMF.R"))
source(here("utils/Add_text_to_figure_panel.R"))2027 Format - Panel Charts with Text Annotations
Introduction
As of January 2027, all staff report charts will need to utilize the new IMF 2027 theme. This section builds on the previous tutorial, but implements all charts using the new 2027 format.
IMF 2027 Format
The transition to the 2027 format is simple, all you need to do is replace the theme functions:
- Replace
theme_imf_panel()withtheme_imf_panel_2027() - Replace
theme_imf()withtheme_imf_2027()
The 2027 theme features:
Arial font (instead of Segoe UI)
Black titles and subtitles (instead of IMF blue)
Updated blue color RGB(0, 76, 151) for accent colors
Everything else in your code remains identical, data processing, layouts, and annotations don’t change at all.
Jamaica Fiscal Panel Charts - 2027 Format
Below we walk through the complete panel charts example using the new 2027 theme functions. Please refer to the previous page for detailed explanations on data processing and chart building techniques.
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.
chart_1_fiscal <- read_excel(here("databases/SR charts v1.xlsx"), sheet = "Chart 1 Data")
chart_2_fiscal <- read_excel(here("databases/SR charts v1.xlsx"), sheet = "Chart 2 Data")
chart_3_fiscal <- read_excel(here("databases/SR charts v1.xlsx"), sheet = "Chart 3 Data")
chart_4_fiscal <- read_excel(here("databases/SR charts v1.xlsx"), sheet = "Chart 4 Data" )
chart_5_fiscal <- read_excel(here("databases/SR charts v1.xlsx"), sheet = "Chart 5 Data" )
chart_6_fiscal <- read_excel(here("databases/SR charts v1.xlsx"), sheet = "Chart 6 Data" )Data Transformation
We need to transform our data into a long format that is suitable for plotting. We’ll define a function chart_long_fiscal for this purpose and apply it to our datasets.
chart_long_fiscal <- function(data){
output <- data %>%
rename(label = Year) %>%
pivot_longer(-label,
names_to = "year",
values_to="value") %>%
mutate(year = as.numeric(year))
return(output)
}
chart_1_fiscal_long <- chart_long_fiscal(chart_1_fiscal)
chart_2_fiscal_long <- chart_long_fiscal(chart_2_fiscal)
chart_3_fiscal_long <- chart_long_fiscal(chart_3_fiscal)
chart_4_fiscal_long <- chart_long_fiscal(chart_4_fiscal)
chart_5_fiscal_long <- chart_long_fiscal(chart_5_fiscal)
chart_6_fiscal_long <- chart_long_fiscal(chart_6_fiscal)
rm(
chart_1_fiscal,
chart_2_fiscal,
chart_3_fiscal,
chart_4_fiscal,
chart_5_fiscal,
chart_6_fiscal
)Creating the Plots
With our data in the correct format, we can now create our visualizations using ggplot2.
fig_chart_1_fiscal <-
chart_1_fiscal_long %>%
ggplot(aes(x = as.character(year),
y=value)) +
geom_bar(stat = "identity",
fill= blue,
position = position_dodge(0.73),
color = "black",
width = 0.42) +
geom_hline(aes(yintercept = 0),
color = light_grey,
linetype= "solid") +
scale_x_discrete(expand = c(0.05,0))+
scale_y_continuous(limits = c(-8,2),
breaks = seq(-8,2,2),
expand = c(0,0)) +
labs(title="Central Government Balance",
subtitle = "(In percent of GDP)",
# caption="Source: Bank of Jamaica (BOJ)",
x="", y= "")+
theme_imf_panel_2027()
fig_chart_1_fiscal
fig_chart_2_fiscal <-
chart_2_fiscal_long %>%
ggplot(aes(x = year,
y= value,
color= label,
linetype = label))+
geom_line(linewidth =1.5)+
scale_x_continuous(limits =c(2010,2020), breaks = 2010:2020)+
scale_y_continuous(limits = c(24,34),
breaks = seq(24,34,2),
expand = c(0,0)) +
labs(title="Central Government Revenues and Expenditures",
subtitle = "(In percent of GDP)",
# caption="Source: Bank of Jamaica (BOJ)",
x="", y= "")+
scale_color_manual(values = c(blue,green)) +
scale_linetype_manual(values = c("solid","dashed")) +
theme_imf_panel_2027()+
theme(legend.title = element_blank(),
legend.position = c(0.57,0.82),
# legend.direction = "vertical",
legend.background = element_blank(),
legend.key.height = unit(0.75, "cm"),
legend.key.width = unit(1.5, "cm"),
legend.spacing.x = unit(0.12,"cm"),
legend.spacing.y = unit(0.20, "cm"))
plot(fig_chart_2_fiscal)
fig_chart_3_fiscal <-
chart_3_fiscal_long %>%
filter(label != "Tax Revenue") %>%
ggplot(aes(x = as.character(year),
y=value,
fill = label)) +
geom_bar(stat = "identity",
position = "stack",
color = "black",
width = 0.42) +
scale_x_discrete(expand = c(0.05,0))+
scale_y_continuous(limits = c(0,30),
breaks = seq(0,30,5),
expand = c(0,0)) +
labs(title="Tax Revenue",
subtitle = "(In percent of GDP)",
# caption="Source: Bank of Jamaica (BOJ)",
x="", y= "")+
scale_fill_manual(values = c(green,blue)) +
theme_imf_panel_2027()+
theme(legend.title = element_blank(),
legend.position = c(0.5,0.92),
legend.direction = "horizontal",
legend.background = element_blank(),
legend.key.height = unit(0.45, "cm"),
legend.key.width = unit(0.55, "cm"),
legend.spacing.x = unit(0.2,"cm"),
legend.spacing.y = unit(0.25, "cm"))+
guides(fill = guide_legend(label.hjust = 1))
fig_chart_3_fiscal
fig_chart_4_fiscal <-
chart_4_fiscal_long %>%
filter(label != "Current spending") %>%
ggplot(aes(x = as.character(year),
y=value,
fill = label)) +
geom_bar(stat = "identity",
position = "stack",
color = "black",
width = 0.42) +
scale_x_discrete(expand = c(0.05,0))+
scale_y_continuous(limits = c(0,35),
breaks = seq(0,35,5),
expand = c(0,0)) +
labs(title="Central Government Current Spending",
subtitle = "(In percent of GDP)",
# caption="Source: Bank of Jamaica (BOJ)",
x="", y= "")+
scale_fill_manual(values = c(green,blue)) +
theme_imf_panel_2027()+
theme(legend.title = element_blank(),
legend.position = "inside",
legend.position.inside = c(0.5,0.9),
legend.direction = "horizontal",
legend.background = element_blank(),
legend.key.height = unit(0.45, "cm"),
legend.key.width = unit(0.55, "cm"),
legend.spacing.x = unit(0.25,"cm"),
legend.spacing.y = unit(0.20, "cm"))
fig_chart_4_fiscal
fig_chart_5_fiscal <-
chart_5_fiscal_long %>%
ggplot(aes(x = as.character(year),
y=value)) +
geom_bar(stat = "identity",
fill= blue,
position = position_dodge(0.73),
color = "black",
width = 0.42) +
geom_hline(aes(yintercept = 0),
color = light_grey,
linetype= "solid") +
scale_x_discrete(expand = c(0.05,0))+
scale_y_continuous(limits = c(0,5),
breaks = seq(0,5,1),
expand = c(0,0)) +
labs(title="Central Government Capital Spending",
subtitle = "(In percent of GDP)",
# caption="Source: Bank of Jamaica (BOJ)",
x="", y= "")+
theme_imf_panel_2027()
fig_chart_5_fiscal
chart_6_fiscal_long <- chart_6_fiscal_long %>%
mutate(Year= as.character(year),
label_chart =
factor(label,
levels = c("Primary Balance (Lhs)"
,"Debt (Rhs)"),
labels= c("Primary Balance (top)",
"Debt (bottom)")))
fig_chart_6_fiscal <-
ggplot()+
geom_line(data= chart_6_fiscal_long %>%
filter(label != "Debt (Rhs)"),
aes(x= year,
y= value,
color = label_chart),
linewidth =1.5) +
geom_bar(data= chart_6_fiscal_long %>%
filter(label == "Debt (Rhs)"),
aes(x= year,
y= value,
fill = label_chart),
position = position_dodge(0.73),
color = "black",
width = 0.42,
stat = "identity") +
scale_x_continuous(limits =c(2009,2026.5),
breaks = 2010:2026,
expand = c(0,0.05)) +
scale_y_continuous( breaks= scales::extended_breaks(n=6),
limits = c(0, NA),
expand = expansion(mult = c(0,0.2))) +
labs(title="Primary Balance and Public Debt",
subtitle = "(In percent of GDP)",
# caption="Source: Bank of Jamaica (BOJ) and IMF Staff Estimates",
x="", y= "") +
scale_color_manual(values = c(blue)) +
scale_fill_manual(values = c(green)) +
facet_wrap(~label_chart,
scales= "free_y",
ncol = 1) +
theme_imf_panel_2027()+
theme(strip.background = element_blank(), strip.text = element_blank(),
panel.spacing = unit(0.15, "lines"))+
theme(legend.title = element_blank(),
legend.position ="inside",
legend.position.inside = c(0.5,0.57),
# legend.direction = "vertical",
legend.box = "horizontal",
legend.background = element_blank(),
legend.key.height = unit(0.45, "cm"),
legend.key.width = unit(0.55, "cm"),
legend.spacing.x = unit(0.1,"cm"),
legend.spacing.y = unit(0.1, "cm"),
axis.text.x = element_text(angle = 45, hjust = 1, vjust = 0.95),
plot.margin = unit(c(0.5,1,0,0.5),"lines"))+
guides(color =guide_legend(order=2,
direction = "horizontal"),
fill = guide_legend(order=2,
direction = "horizontal"))
fig_chart_6_fiscal
fig_chart_1_fiscal_text <-
"The COVID-19 shock led to a sharp increase in central government's \nfiscal deficit and debt levels..."
fig_chart_1_fiscal_panel <-
AddTextToFigure(fig_chart_1_fiscal,fig_chart_1_fiscal_text)
fig_chart_2_fiscal_text <-
"...the revenue-to-GDP ratio declined and the expenditure-to-GDP \nratio increased."
fig_chart_2_fiscal_panel <-
AddTextToFigure(fig_chart_2_fiscal,fig_chart_2_fiscal_text)
fig_chart_3_fiscal_text <-
"Lower tax revenues in FY 2020 were the result of a decline in GDP and GCT\ntax cuts."
fig_chart_3_fiscal_panel <-
AddTextToFigure(fig_chart_3_fiscal,fig_chart_3_fiscal_text,0.58)
fig_chart_4_fiscal_text <-
"The increase in the spending ratio was largely the result of the decline in \nGDP."
fig_chart_4_fiscal_panel <-
AddTextToFigure(fig_chart_4_fiscal,fig_chart_4_fiscal_text,0.58)
fig_chart_5_fiscal_text <-
"While capital spending was held back to make room for COVID-19 \nrelated spending..."
fig_chart_5_fiscal_panel <-
AddTextToFigure(fig_chart_5_fiscal,fig_chart_5_fiscal_text,0.51)
fig_chart_6_fiscal_text <-
"...public debt rose in FY 2020 but is on a downward path to meet the FRL \ntarget."
fig_chart_6_fiscal_panel <-
AddTextToFigure(fig_chart_6_fiscal,fig_chart_6_fiscal_text,0.51)Combining and Saving the Plots
When combining charts with patchwork and adding an overall figure title using plot_annotation(), in this interim period where two formats are available, you’ll need to explicitly update the color and font settings to match the 2027 theme:
- Change
family=primary_fonttofamily=primary_font_2027(for Arial font) - Change
color=bluetocolor=blue_2027(for the updated 2027 blue)
This ensures your panel title matches the styling of the individual charts below it.
patchwork_layout_2 <-
(fig_chart_1_fiscal_panel|fig_chart_2_fiscal_panel)/
(fig_chart_3_fiscal_panel|fig_chart_4_fiscal_panel)/
(fig_chart_5_fiscal_panel|fig_chart_6_fiscal_panel)
patchwork_output_2<- patchwork_layout_2 + plot_annotation(
title = 'Figure 7. Fiscal Sector Developments',
# subtitle = '(In constant US dollars)',
caption="Sources: Bank of Jamaica and IMF staff estimates and projections.",
theme = theme(plot.title = element_text(color=blue_2027,
family=primary_font_2027,face="bold",
size=20, hjust = 0.5),
plot.subtitle = element_text(color="black",
family=primary_font_2027,
face="plain",
hjust=0.5,
size=20),
plot.caption = element_text(hjust = 0,size=12,
family=primary_font_2027,
),
plot.margin = margin(0.75,0.5,0.5,0.5, "lines")
))
patchwork_output_2
Finally, we save the combined plot to a file.
ggsave(
here("figures/panel-figure-2-fiscal.png"),
plot = patchwork_output_2,
dpi = 600,
width = 12.51,
height = 15.64 ,
units = "in"
)You’ve now seen how to build a complete panel chart visualization using the IMF 2027 theme. Notice that all the work, data import, transformation, annotation, and layout, remains identical to the original tutorial. The only changes needed were swapping theme_imf_panel() for theme_imf_panel_2027() on each chart.