Motivations

The line chart bellow was inspired by this article:

R codes

R codes for creating the chart:

# Clear R environment: 

rm(list = ls())

# Load some R packages: 

library(rvest)
library(magrittr)
library(tidyverse)

# Load admission data for Ivy Colleges: 

link <- "https://www.ivycoach.com/ivy-league-statistics-by-college/"

admissions <- read_html(link) %>% 
  html_table(fill = TRUE, header = FALSE)

# Number of Ivy Colleges: 
n <- length(admissions)

# Function processes data for each college: 

process_college <- function(j) {
  
  admissions[[j]] -> college_j
  
  college_j %>% 
    slice(1) %>%
    as.vector() %>% 
    str_replace_all("[^a-z|A-Z]", "") %>% 
    str_replace_all("University", "") -> col_names
  
  col_names[1] -> Univ_Name
  
  col_names[1] <- "Year"
  
  names(college_j) <- col_names
  
  college_j %>% 
    slice(-1) %>% 
    mutate(Univ_Name = Univ_Name) -> final_df
  
  return(final_df)
  
}

# Convert data for data frame: 

lapply(1:n, process_college) -> admissions_data

do.call("bind_rows", admissions_data) -> admissions_data


# Function convert to numeric: 

convert_to_num1 <- function(x) {
  
  x %>% 
    str_replace_all("\\.", ",") %>% 
    str_replace_all(",", "") %>% 
    as.numeric() %>% 
    return()
}


# Calculate accept rate: 

admissions_data %>% 
  select(Year, TotalAppsAccepted, TotalAppsReceived,  Univ_Name) %>% 
  mutate(Year = as.numeric(Year), acc_rate = 100*convert_to_num1(TotalAppsAccepted) / convert_to_num1(TotalAppsReceived)) %>% 
  mutate(Univ_Name = case_when(Univ_Name == "DartmouthCollege" ~ "Dartmouth", 
                               Univ_Name == "ofPennsylvania" ~ "Pennsylvania", 
                               TRUE ~ Univ_Name)) -> df_for_line

# Set colors for ploting: 

color_bgr <- "#1d1330"

df_for_line %>% 
  filter(Year == 2025) %>% 
  mutate(label = as.character(round(acc_rate, 1))) %>% 
  mutate(label = case_when(str_detect(label, "\\.") ~ label, 
                           TRUE ~ str_c(label, ".0"))) -> df_2025

df_for_line %>% 
  filter(Year == 2007) %>% 
  mutate(label = as.character(round(acc_rate, 1))) %>% 
  mutate(label = case_when(str_detect(label, "\\.") ~ label, 
                           TRUE ~ str_c(label, ".0"))) -> df_2007


library(showtext) # -> Package for using extra fonts. 

font_subtitle <- "Roboto Condensed"  # -> Set Outfit font for our plot. 

font_add_google(name = font_subtitle, family = font_subtitle) # -> Load font for using. 

font_text <- "Oswald"

font_add_google(name = font_text, family = font_text)

font_main <- "Ubuntu"  

font_add_google(name = font_main, family = font_main) 

# Automatically render text: 
showtext_auto()

x_label <- c("2007", rep("", 17), "2025", rep("", 4))


df_for_line %>% 
  filter(Year == 2016) %>% 
  mutate(acc_rate = 3.1) -> df_annotation

p_title <- "Ivy League Acceptance Rates 2007 - 2025"

p_caption <- "Source: IVY COACH | Graphic Designer: Nguyen Chi Dung"

p_subtitle <- "Acceptance rates are decreasing across all Ivy League schools from 2007 to 2025. Harvard is not just\nthe most selective of the Ivies, but it typically ranks as the most selective university in the United States."


df_for_line %>% 
  ggplot(aes(x = Year, y = acc_rate, group = Univ_Name )) + 
  geom_area(fill = "cyan", alpha = 0.1) +
  geom_line(color = "cyan", size = 0.5) + 
  geom_point(data = df_2025, shape = 21, size = 2, color = "cyan", fill = "cyan") + 
  geom_text(data = df_2025, aes(label = label), color = "white", 
            hjust = -0.3, family = font_subtitle, size = 4, fontface = "bold") + 
  geom_point(data = df_2007, shape = 21, size = 2, color = "cyan", fill = "cyan") + 
  geom_text(data = df_2007, aes(label = label), color = "white", 
            vjust = -1, hjust = 0.2, family = font_subtitle, size = 4, fontface = "bold") + 
  facet_wrap(~ Univ_Name, nrow = 2, scales = "free_x") + 
  scale_x_continuous(breaks = seq(2007, 2029, 1), labels = x_label, limits = c(2007, 2029)) + 
  scale_y_continuous(expand = c(0, 0), limits = c(0, 37)) + 
  theme(panel.grid.minor.y = element_blank()) + 
  theme(panel.grid.major.x = element_blank()) + 
  theme(panel.grid.minor.x = element_blank()) + 
  theme(axis.title = element_blank()) + 
  theme(axis.text.y = element_blank()) + 
  theme(plot.background = element_rect(fill = color_bgr, color = NA)) + 
  theme(panel.background = element_rect(fill = color_bgr, color = NA)) + 
  theme(panel.grid = element_blank()) + 
  theme(axis.ticks = element_blank()) +
  geom_hline(yintercept = 0, color = color_bgr, size = 0.7) + 
  theme(axis.text.x = element_text(family = font_main, color = "white", size = 11)) + 
  theme(strip.background = element_rect(fill = color_bgr)) + 
  geom_text(data = df_annotation, aes(label = Univ_Name), color = "white", family = font_main, size = 4, fontface = "bold") + 
  theme(plot.margin = unit(rep(0.7, 4), "cm")) + 
  labs(title = p_title, subtitle = p_subtitle, caption = p_caption) + 
  theme(plot.title = element_text(family = font_main, color = "white", size = 20, face = "bold"), 
        plot.subtitle = element_text(family = font_main, color = "grey90", size = 11), 
        plot.caption = element_text(family = font_main, color = "grey70", size = 9, hjust = 0, vjust = -3)) + 
  theme(plot.title.position = "plot")