Motivations

The Economist là tạp chí hàng đầu với những chart đẹp và nhiều thông tin. Tuy vậy tạp chí này cũng tạo ra những misleading charts. Shara Leo - visual data journalist của tạp chí này list một loạt những chart gây hiểu lầm này cũng như phương án thay thế tại đây.

Bằng R/ggplot2 chúng ta có thể tạo barplot với những hiệu chỉnh/sửa đổi như sau:

R Codes

R Codes cho plot ở trên:

#-----------------------------
#  Prepare data for ploting
#-----------------------------

# Clear R environment: 
rm(list = ls())

# Load data: 
library(tidyverse)

read_csv("http://infographics.economist.com/databank/Economist_eu-balance.csv") -> our_data

new_names <- c("nation", str_c("current", 2009:2015), str_c("budget", 2009:2015))

names(our_data) <- new_names

some_nations1 <- c("Germany", "Greece", "Netherlands", "Spain")

some_nations2 <- c("Austria", "Belgium", "France", "Ireland", "Italy", "Portugal")

our_data %>% 
  filter(nation %in% c(some_nations1, some_nations2)) %>% 
  mutate(nation_new = case_when(nation %in% some_nations1 ~ nation, 
                                TRUE ~ "Others")) -> data_for_ploting

data_for_ploting %>% 
  select(-nation) %>% 
  group_by(nation_new) %>% 
  summarise_all(sum) %>% 
  ungroup() %>% 
  gather(acc_type, balance, - nation_new) %>% 
  arrange(nation_new) %>% 
  mutate(year = str_replace_all(acc_type, "[^0-9]", "")) %>% 
  mutate(year = as.numeric(year)) %>% 
  mutate(acc_type = str_replace_all(acc_type, "[0-9]", "")) %>% 
  mutate(acc_type = case_when(acc_type == "current" ~ "Current-account balance", TRUE ~ "Budget balance")) %>% 
  mutate(balance = balance / 1000) %>% 
  mutate(acc_type = factor(acc_type, levels = c("Budget balance", "Current-account balance"))) %>% 
  mutate(nation_new = factor(nation_new, levels = c(some_nations1, "Others"))) -> df_long


# The Economist colors (from https://www.economist.com/finance-and-economics/2016/09/03/more-spend-less-thrift): 

germany_color <- "#e4a52a"

greece_color <- "#206e73"

nether_color <- "#02a4db" 

spain_color <- "#e55743" 

others_color <- "#80a6b1"

red_icon <- "#ed1c24"

bgr_color <- "#d9e9f0"

#-----------------------------------
#  Data Vis - Version 1: Bar Plot
#-----------------------------------

p_title <- "Surfeit of surpluses"

p_subtitle <- "Euro-area, €bn"

p_caption <- "Source: Eurostast; National Statistics | Graphic Designer: Nguyen Chi Dung"

library(showtext) # Package for using extra fonts. 

# Load font for ploting: 

my_font <- "Roboto Condensed" 

font_add_google(name = my_font, family = my_font) 

showtext_auto() # Automatically render text. 


labels_x <- as.character(2009:2016)

case_when(labels_x == "2009" ~ labels_x, TRUE ~ str_sub(labels_x, 3, 4)) -> labels_x


library(ggh4x)

labels_x <- as.character(2009:2016)

case_when(labels_x == "2009" ~ "2009", 
          labels_x == "2016" ~ "", 
          TRUE ~ str_sub(labels_x, 3, 4)) -> labels_x


df_long %>% 
  filter(acc_type == "Budget balance") %>% 
  slice(1:8) %>% 
  mutate(balance = seq(-600, 100, 100) + 20) -> df_left

label_y_left <- as.character(seq(-600, 100, 100))

df_long %>% 
  filter(acc_type != "Budget balance") %>% 
  slice(1:7) %>% 
  mutate(balance = seq(-200, 400, 100) + 20) -> df_right

label_y_right <- as.character(seq(-200, 400, 100))


df_long %>% 
  ggplot(aes(x = year, y = balance, fill = nation_new)) + 
  geom_col(width = 0.75) + 
  facet_wrap(acc_type ~ ., scales = "free") + 
  scale_fill_manual(values = c(Germany = germany_color, 
                               Greece = greece_color, 
                               Netherlands = nether_color, 
                               Spain = spain_color, 
                               Others = others_color)) + 
  labs(title = p_title, subtitle = p_subtitle, caption = p_caption) + 
  theme(legend.position = "top") + 
  # Make The Economist Theme: 
  theme(plot.background = element_rect(fill = bgr_color, color = NA)) + 
  theme(panel.background = element_rect(fill = bgr_color, color = NA)) + 
  # Adjust legend: 
  theme(legend.title = element_blank()) + 
  theme(legend.text = element_text(size = 12, color = "grey30", family = my_font)) + 
  theme(legend.key.height = unit(0.4, "cm")) + 
  theme(legend.key.width = unit(0.4, "cm")) + 
  theme(legend.background = element_rect(fill = bgr_color)) + 
  # Adjust strip panel: 
  theme(strip.background = element_rect(fill = bgr_color)) + 
  theme(strip.text = element_text(color = "grey20", family = my_font, hjust = -0.04, size = 13, face = "bold")) + 
  # Adjust axis: 
  theme(axis.title = element_blank()) + 
  theme(axis.text.y = element_blank()) + 
  theme(axis.ticks.y = element_blank()) + 
  theme(panel.grid.minor = element_blank()) + 
  theme(panel.grid.major.x = element_blank()) +
  # Adjust margins: 
  theme(plot.margin = unit(rep(0.6, 4), "cm")) + 
  scale_x_continuous(breaks = seq(2009, 2016, 1), expand = c(0, 0), limits = c(2008.6, 2016.3), labels = labels_x) + 
  facetted_pos_scales(
    y = list(
      acc_type == "Budget balance" ~ scale_y_continuous(limits = c(-600, 120), breaks = seq(-600, 100, 100)), 
      acc_type != "Budget balance" ~ scale_y_continuous(limits = c(-200, 420), breaks = seq(-200, 400, 100))
    )
  ) -> p 
  
  
p + 
  geom_text(data = df_left, aes(x = 2015.9, label = label_y_left), color = "grey30", family = my_font, size = 4.5) + 
  geom_text(data = df_right, aes(x = 2015.9, label = label_y_right), color = "grey30", family = my_font, size = 4.5) + 
  geom_hline(yintercept = 0, color = "#e56059", size = 1) + 
  theme(axis.ticks.length.x = unit(0.2, "cm")) +  
  theme(axis.ticks.x = element_line(color = c(rep("grey40", 7), bgr_color), size = 0.75)) +  
  theme(axis.line.x = element_line(color = "grey40", size = 0.75)) + 
  # theme(legend.justification = "left") + 
  theme(axis.text.x = element_text(family = my_font, size = 12, color = "grey30")) + 
  theme(plot.title = element_text(family = my_font, size = 17, face = "bold")) + 
  theme(plot.subtitle = element_text(family = my_font, size = 14, color = "grey20")) + 
  theme(panel.grid = element_line(color = "white", size = 0.75)) + 
  theme(plot.caption = element_text(family = my_font, color = "grey40", size = 11, hjust = 0, vjust = -1)) + 
  theme(legend.justification = "left") + 
  theme(plot.title.position = "plot") + 
  theme(legend.margin = margin(c(5, 0, 0, -7)))
  

# Make Financial Times icon: 

library(grid)

grid.rect(x = 0.035, y = 1, width = 0.05, height = 0.008*2.5, just = c("left", "top"), gp = gpar(fill = red_icon, col = red_icon))