Load the data

We used data that shows the distribution of human rights index among countries in different continents. Higher values represent more rights.

library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.1     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.1
## ✔ purrr     1.0.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
humanrights <- readr::read_csv("https://ourworldindata.org/grapher/distribution-human-rights-index-vdem.csv?v=1&csvType=filtered&useColumnShortNames=true&time=latest")
## New names:
## Rows: 298 Columns: 7
## ── Column specification
## ──────────────────────────────────────────────────────── Delimiter: "," chr
## (3): Entity, Code, owid_region dbl (4): Year,
## civ_libs_vdem__estimate_best__aggregate_method_average, time....
## ℹ Use `spec()` to retrieve the full column specification for this data. ℹ
## Specify the column types or set `show_col_types = FALSE` to quiet this message.
## • `time` -> `time...6`
## • `time` -> `time...7`
glimpse(humanrights)
## Rows: 298
## Columns: 7
## $ Entity                                                 <chr> "Afghanistan", …
## $ Code                                                   <chr> "AFG", NA, "ALA…
## $ Year                                                   <dbl> 2023, 2023, 202…
## $ civ_libs_vdem__estimate_best__aggregate_method_average <dbl> 0.0530000, 0.59…
## $ owid_region                                            <chr> "Asia", NA, "Eu…
## $ time...6                                               <dbl> 2023, 2023, 202…
## $ time...7                                               <dbl> 2023, 2023, 202…

Replica graph

We recreated the graph, matching aesthetics like colors, labels, and scales.

library(ggplot2)
library(dplyr)

# Identify the country with the lowest human rights index
lowest_country <- humanrights %>%
  filter(!is.na(civ_libs_vdem__estimate_best__aggregate_method_average)) %>% 
  slice_min(civ_libs_vdem__estimate_best__aggregate_method_average, n = 1) %>%
  pull(Entity)

# Dynamically create the x-axis labels up to the lowest country
x_labels <- humanrights %>%
  arrange(desc(civ_libs_vdem__estimate_best__aggregate_method_average)) %>%
  pull(Entity) %>%
  .[1:which(. == lowest_country)]

x_labels2 <- c("New Zealand", "Chile", "Slovakia", "United Kingdom", "Albania", "Solomon Islands", "Zambia", "Colombia", "Malaysia", "Singapore", "Morocco", "Kyrgyzstan", "Thailand", "Vietnam", "Cambodia", "Rwanda", "North Korea")

custom_colors <- c(
  "Europe" = "#8197B8", 
  "Asia" = "#64A9A5",    
  "Africa" = "#BE88B9",  
  "Oceania" = "#7BC4CF",  
  "North America" = "#EF9B8C", 
  "South America" = "#AE7074" 
)

# Plot with the x-axis ending at the lowest index country
ggplot(humanrights) +
  geom_col(aes(x = reorder(Entity, -civ_libs_vdem__estimate_best__aggregate_method_average), 
               y = civ_libs_vdem__estimate_best__aggregate_method_average, 
               fill = owid_region)) +
  scale_y_continuous(breaks = seq(0, 1, 0.2), limits = c(0, 1)) +
  scale_x_discrete(limits = x_labels, breaks = x_labels2, labels = x_labels2) + # Limit x-axis to include up to the lowest country
    scale_fill_manual(values = custom_colors) +  # Apply custom colors
  labs(x = "", y = "Human rights", title = "Distribution of human rights index, 2023") +
theme(axis.text.x = element_text(angle = 45, hjust = 1), legend.title = element_blank(), 
        legend.position = "top", legend.direction = "horizontal", legend.justification = "left", legend.text = element_text(size = 8),
    panel.background = element_rect(fill = "white", color = NA),  # White background
    panel.grid.major.x = element_blank(),                        # No x-axis grid
    panel.grid.minor.x = element_blank(),                        # No minor x-axis grid
    panel.grid.major.y = element_blank(),                        # Remove default y-axis grid
    panel.grid.minor.y = element_blank(),                        # Remove minor y-axis grid
    plot.background = element_rect(fill = "white"),              # Ensure overall plot has a white background
    panel.grid = element_line(color = "grey80", linetype = "dotted", size = 0.5), # Dots for y intervals
    plot.title = element_text(
      family = "Times New Roman",
      size = 20,
      color = "#636363",
      face = "bold")) +
  annotate("segment", x = -Inf, xend = Inf, y = seq(0, 1, 0.2), yend = seq(0, 1, 0.2),
           color = "grey80", size = 0.5, linetype = "dotted") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))
## Warning: The `size` argument of `element_line()` is deprecated as of ggplot2 3.4.0.
## ℹ Please use the `linewidth` argument instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## Warning: Removed 113 rows containing missing values or values outside the scale range
## (`geom_col()`).

Changed plot

We made changes to the plot to make the data more intuitive to understand how human rights differ across continents.

library(ggplot2)
library(dplyr)
library(viridis)
## Loading required package: viridisLite
library(patchwork)

# Filter out rows with NA values for y-axis labels
humanrights_filtered <- humanrights %>%
  filter(!is.na(civ_libs_vdem__estimate_best__aggregate_method_average))

# Function to create labels with region-specific intervals
create_labels <- function(data, region_name) {
  if (region_name == "Oceania") {
    labels <- data$Entity  # Label all countries for Oceania
  } else if (region_name == "South America") {
    labels <- ifelse(seq_along(data$Entity) %% 2 == 1, data$Entity, "")  # Label every 2nd country for South America
  } else if (region_name == "North America") {
    labels <- ifelse(seq_along(data$Entity) %% 3 == 1, data$Entity, "")  # Label every 3rd country for North America
  } else if (region_name %in% c("Africa", "Asia", "Europe")) {
    labels <- ifelse(seq_along(data$Entity) %% 10 == 1, data$Entity, "")  # Label every 10th country for Africa, Asia, and Europe
  } else {
    labels <- ifelse(seq_along(data$Entity) %% 3 == 1, data$Entity, "")  # Label every 3rd country for other regions
  }
  labels
}

# Create the base plot for each region
base_plot <- function(region_data, region_name) {
  region_data <- region_data %>% arrange(-civ_libs_vdem__estimate_best__aggregate_method_average)
  labels <- create_labels(region_data, region_name)
  
  ggplot(region_data) +
    geom_col(aes(y = reorder(Entity, -civ_libs_vdem__estimate_best__aggregate_method_average), 
                 x = civ_libs_vdem__estimate_best__aggregate_method_average, 
                 fill = civ_libs_vdem__estimate_best__aggregate_method_average)) +
    scale_x_continuous(breaks = seq(0, 1, 0.1), limits = c(0, 1)) +
    scale_fill_viridis_c(option = "mako", direction = 1, limits = c(0, 1), breaks = c(0, 1)) +
    labs(x = "Human rights index", 
         y = "", 
         fill = "Human Rights\nIndex",
         title = region_name) +
    theme_minimal() +
    theme(
      plot.title = element_text(size = 12, face = "bold"),
      axis.text.x = element_text(size = 8, angle = 0, hjust = 0.5),
      axis.text.y = element_text(size = 8),
      axis.ticks.y = element_blank(),                # Remove tick marks on the y-axis
      axis.title.y = element_text(size = 10, angle = 0, vjust = 0.5),
      axis.title.x = element_text(size = 10),
      legend.position = "right"
    ) +
    scale_y_discrete(labels = labels, 
                     expand = expansion(add = c(0.5, 0.5))) 
}

# Create individual plots for each region
plots <- humanrights_filtered %>%
  split(.$owid_region) %>%
  purrr::imap(~ base_plot(.x, .y))

# Combine the plots with patchwork
combined_plot <- wrap_plots(plots, ncol = 2) + 
  plot_layout(guides = "collect") & 
  theme(legend.position = "right", 
        legend.title = element_text(size = 10),
        plot.title = element_text(
          
          size = 12,
          color = "#636363",
          face = "bold"))

# Add a big title over the whole plot
combined_plot + plot_annotation(title = "Distribution of human rights index, 2023", 
                                theme = theme(plot.title = element_text(size = 22, family = "Times New Roman", face = "bold", hjust = 0.5)))

Explanantion

Our first impression of the original graph was that it presented an overwhelming amount of information in a way that was not immediately intuitive to discern. In class, we discussed how we want graph readers to use as little cognitive energy trying to remember the information presented on graphs as possible, and this graph would certainly pose a large cognitive load. Also, while the graph did make an attempt at distinguishing what countries belonged to which continents via using different colors, we thought the difference between continents should be more clear.

In our version of the graph, we began by faceting the continents, such that each continent had its own graph, using “patchwork,” which we learned in class. That way, it became much easier to compare countries within the same continent, and then compare overall trends in human rights development between continents. Also, we chose to create a color gradient signifying human rights index level, with 1 being light blue, and 0 being dark blue. This was done in order to more clearly display the level of variation in human rights development within each country. It also more clearly demonstrated similarities across countries and continents; for instance, most countries in Europe are the same dark blue, telling us that these countries have relatively similar human development indexes. Next, we switched the x and y-axises. That meant that the country names could be on the left, so they could be read horizontally, making things easier for graph viewers. We only had space to show a few countries in each continent, so we tried to space the country names on each graph so that they looked roughly similar, for legibility and aesthetic purposes. Then, we flipped the legend, so that the light color, representing a high human rights index, was on top. This is intuitive, since higher often means higher in quantity, and lower means lower in quantity. Finally, we changed the scale to go up by 0.1 instead of 0.2, because this could allow graph viewers to notice a more specific degree of variance.