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
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.
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.
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.
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.
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()
Lack of Contextual Baseline & Reference
Line: The initial chart only showed a plain trend line without
any benchmark. It lacked a historical average line (e.g.,
Avg = 7,771.31), making it difficult for viewers to
immediately tell whether unemployment at any given point was above or
below normal levels.
Missing Color Hierarchy: The single black line offered no visual contrast, making the chart look plain and non-executive ready.
Absence of Descriptive Subtitle: The title gave no context regarding the dataset’s coverage period (1967–2015) or frequency (monthly).
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.
Added Baseline Reference: Introduced a dashed
red line via geom_hline() marking the historical average
(Avg = 7,771.31) to establish an instant visual
benchmark.
Background Zone Shading: Incorporated soft green
(Above-Average Zone) and soft red
(Below-Average Zone) shaded rectangles using
annotate("rect") to segment high economic stress from
stability.
Direct On-Graph Text: Placed embedded text
labels using annotate("text") directly onto the plot area
to highlight key zones and the mean metric without clutter.
Enhanced Visual Hierarchy: Replaced the standard
black line with a dark blue line (#1E3A8A) for better
visual contrast against the shaded zones.
Complete Context & Metadata: Added a descriptive subtitle clarifying the 1967–2015 timeframe and a formal data source caption at the bottom.
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.