library(ggplot2)
library(ggridges)
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
## ✔ lubridate 1.9.4     ✔ tibble    3.2.1
## ✔ purrr     1.0.2     ✔ tidyr     1.3.1
## ── 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

1. Comparison - mpg

Calculate the average cty for each manufacturer, select the top 10, create a comparison plot, and summarize the main finding

top10cty <- mpg %>%
  group_by(manufacturer) %>%
  summarise(avg_cty=mean(cty))%>%
  arrange(desc(avg_cty))%>%
  head(10)
ggplot(top10cty, aes(x = reorder(manufacturer, -avg_cty), y = avg_cty)) +
  geom_col(fill = "#2c3e50", alpha=0.7)+
  labs(
    title = "Top 10 Automobile Manufacturers by Average City Fuel Efficiency",
    subtitle = "Average city fuel consumption in Miles Per Gallon (MPG)",
    x = "Manufacturer", 
    y = "Average City MPG (cty)",
    caption = "Source: ggplot2 mpg dataset"
    )+ 
  geom_text(aes(label = round(avg_cty, 1)), vjust = -0.5, size = 3.5)+
  theme_classic()

Graph Interpretation:

The chart reveals that Honda outperforms all other manufacturers in city fuel efficiency with an average of 24.4 MPG, followed by Volkswagen (20.9 MPG) and Subaru (19.3 MPG), demonstrating a strong dominance by Asian and European brands in the top rankings. Conversely, American automakers like Pontiac (17 MPG), Chevrolet (15 MPG), and Ford (14 MPG) occupy the lower positions of the top 10, highlighting a significant performance gap of 10.4 MPG between the highest and lowest-ranked manufacturers in this group.

Code Explanation:

The code first aggregates the mpg dataset by manufacturer to calculate average city mileage, sorts the results, and selects the top 10 rows using head(10). It then generates a bar chart using ggplot() and geom_col(), where reorder() arranges the bars from highest to lowest. Finally, numeric values are displayed above each bar via geom_text(), while labs() and theme_classic() provide clear labels and a clean aesthetic.

2. Distribution - diamonds

Choose one numerical variable, compare its distribution across one categorical variable, improve the plot appearance, and interpret the pattern

ggplot(diamonds,  aes(x=price,y=cut, fill=cut, col=cut))+
  geom_density_ridges(alpha=0.5)+
  labs(
    title = "Price Distribution Across Diamond Cut Qualities",
    subtitle = "Comparing density curves of diamond prices by cut classification",
    x = "Price (USD)",
    y = "Cut Quality",
    caption = "Source: ggplot2 diamonds dataset"
  )+
  theme_minimal()
## Picking joint bandwidth of 458

Graph Interpretation: The ridgeline plot reveals that diamond prices across all cut qualities are strongly right-skewed, with the highest concentration of prices clustered below $2,500. Higher-grade cuts like Ideal, Premium, and VeryGood show sharp peaks at the lower end of the price scale alongside a subtle secondary bump around $4,000 to $5,000. In contrast, the Fair cut displays a flatter, wider distribution peak centered around $2,500, indicating that lower-quality cuts in this dataset do not necessarily translate to lower prices due to confounding factors like higher average carat weights.

Code Explanation: The code generates a ridgeline plot using ggplot() and geom_density_ridges() from the ggridges package, mapping price to the x-axis and cut to the y-axis to compare price distributions vertically across cut categories. The parameters fill = cut and col = cut color both the inside and outline of each density curve, while alpha = 0.5 adds transparency to keep overlapping areas visible. Finally, labs() updates the title, subtitle, axis labels, and caption, and theme_minimal() applies a clean background layout.

3. Relationship - diamonds_sample

Visualize the relationship between carat and price, add at least one relevant aesthetic, apply suitable customization, and explain the relationship shown.

set.seed(123) 
diamonds_sample <- diamonds%>%
  slice_sample(n = 10000)
ggplot(diamonds_sample, aes(x = carat, y = price, col = cut)) +
  geom_point(alpha = 0.5) +
  labs(
    title = "Relationship Between Diamond Carat Weight and Price",
    subtitle = "Scatter plot comparing carat weight and price categorized by cut quality",
    x = "Carat Weight",
    y = "Price (USD)",
    color = "Cut Quality",
    caption = "Source: ggplot2 diamonds dataset"
  ) +
  theme_minimal() 

Graph Interpretation:

The scatter plot reveals a strong, positive, non-linear relationship between diamond carat weight and price. At lower carat weights (below 1.0 carat), prices are tightly clustered below $5,000. As carat weight increases, price rises exponentially, showing noticeable vertical clustering near full integer weights like 1.0, 1.5, and 2.0 carats. Diamonds with higher-grade cuts such as Ideal and Very Good are densely concentrated at higher price points for any given carat weight, whereas Fair cut diamonds tend to cluster toward the lower price boundary across the carat spectrum.

Code Explanation:

The code generates a scatter plot using ggplot() and geom_point(), mapping carat to the x-axis, price to the y-axis, and cut to the col parameter to color data points by cut quality. The parameter alpha = 0.5 introduces semi-transparency to keep overlapping points distinguishable, while scale_color_brewer() applies the Set1 color palette to differentiate the cut categories. Finally, labs() sets the title, subtitle, axis titles, legend label, and caption, and theme_minimal() applies a clean, modern background layout.

4. Time Series - economics

Visualize psavert over time, use clear labels and a suitable theme, highlight or annotate a noticeable change, and provide a short interpretation.

economics %>% 
  select(date, unemploy, psavert) %>% 
  head()
## # A tibble: 6 × 3
##   date       unemploy psavert
##   <date>        <dbl>   <dbl>
## 1 1967-07-01     2944    12.6
## 2 1967-08-01     2945    12.6
## 3 1967-09-01     2958    11.9
## 4 1967-10-01     3143    12.9
## 5 1967-11-01     3066    12.8
## 6 1967-12-01     3018    11.8
ggplot(data = economics, 
       aes(x = date, y = unemploy)) + 
  geom_line(linewidth = 0.7) +  
  labs(    
    title = "US Unemployment Growth Over Time",    
    x = "Date",    
    y = "Number of Unemployed (in thousands)"  ) +  
  theme_minimal()

Graph Interpretation:

The line chart displays the historical trend of US unemployment counts from 1967 to 2015. Starting at relatively low levels under 4,000 thousand in the late 1960s, the unemployment series displays cyclical fluctuations with prominent spikes corresponding to economic downturns—notably around 1982–1983 and 1992. The most significant rise occurred around 2009–2010, where unemployment reached its historical peak above 15,000 thousand individuals following the global financial crisis, before entering a period of steady decline.

Code Explanation:

The pipeline first uses select() and head() to isolate and preview key columns (date, unemploy, and psavert) from the economics dataset. To generate the chart, ggplot() maps date to the x-axis and unemploy to the y-axis, while geom_line(linewidth = 0.7) plots a solid black time-series line with custom thickness. The labs() function updates the main title and axis names with proper labels and units (Number of Unemployed (in thousands)), and theme_minimal() applies a clean, modern grid layout.

5. Improve a Visualization

Create one visualization with at least three presentation problems, then redesign it using improvements such as color, theme, scale, labels, legend, or annotation, and briefly explain the changes

5.a. The Flawed Visualization (Before)

ggplot(data = economics, 
       aes(x = date, y = unemploy)) + 
  geom_line(linewidth = 0.7) +  
  labs(    
    title = "US Unemployment Growth Over Time",    
    x = "Date",    
    y = "Number of Unemployed (in thousands)"  ) +  
  theme_minimal()

5.b. Redesigned Visualization (After)

ggplot(data = economics, aes(x = date, y = unemploy))+
  annotate("rect", 
           xmin = min(economics$date), 
           xmax = max(economics$date), 
           ymin = 7771.31, 
           ymax = max(economics$unemploy), 
           fill = "#E8F5E9", 
           alpha = 0.6)+
  annotate("rect", 
           xmin = min(economics$date), 
           xmax = max(economics$date), 
           ymin = min(economics$unemploy), 
           ymax = 7771.31, 
           fill = "#FFEBEE", 
           alpha = 0.6)+
  
  geom_line(color = "#1E3A8A", size = 0.5) + 
  geom_hline(yintercept = mean(economics$unemploy, na.rm = TRUE),color="#DC2626",linetype = "dashed")+
  
  
  labs(
    title = "US Unemployment Growth Over Time",
    subtitle = "Analysis of monthly unemployment trends relative to the historical average (1967–2015)",
    x = "Date",
    y = "Number of Unemployed (in thousands)",
    caption = "Source: US Presidential Economic Report (economics dataset)"
  ) +
  
  annotate("text",
           x=as.Date("1970-07-01"),
           y=8400,
           label="Avg = 7771.31",
           color="#DC2626",
           fontface="bold",
           size=3.3,
           alpha=4)+
  annotate("text",
           x=as.Date("1975-07-01"),
           y=14500,
           label="Above-Average Zone\n(High Coverage)",
           color="#166534",
           fontface="bold",
           size=3.3,
           alpha=4)+
  annotate("text",
           x=as.Date("2007-07-01"),
           y=4000,
           label="Below-Average Zone\n(Lower Coverage)",
           color="#991B1B",
           fontface="bold",
           size=3.3,
           alpha=4)+
  
  
  theme_minimal()
## 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.

Graph Interpretation:

The line chart tracks the US monthly unemployment count from July 1967 to April 2015, evaluated against a historical mean threshold of 7,771.31 thousand unemployed individuals. The plot is divided into two distinct regions: the light green shaded Above-Average Zone (High Coverage) above the baseline and the light red shaded Below-Average Zone (Lower Coverage) below it. Unemployment remained consistently low throughout the late 1960s before experiencing recurring cyclical surges. Major peaks occurred during economic downturns in the early 1980s and early 1990s, culminating in an all-time peak exceeding 15,000 thousand during the 2008–2010 global financial crisis before trending downward.

Code Explanation:

The pipeline begins with select() and head() to preview the relevant time-series variables from the economics dataset. The visualization uses ggplot() and geom_line() with a dark blue stroke (#1E3A8A) to map unemployment over time. Two background rectangle annotations (annotate("rect")) shade the entire date range (min to max date): green (#E8F5E9) for values above the mean and light red (#FFEBEE) for values below. A horizontal red dashed line (geom_hline()) marks the exact mean value (7,771.31) calculated via mean(unemploy, na.rm = TRUE). Custom textual annotations (annotate("text")) are positioned using specific dates and y-coordinates to label the baseline average and zone names. Finally, labs() updates all titles, axis names, and captions in English, while theme_minimal() applies a clean, modern grid layout.