Chapter 36: R Plotting
R Plotting — probably the single most enjoyable (and addictive) part of learning R.
Many people fall in love with R exactly because of how beautiful and flexible the plots can be. You can go from a quick 3-line exploratory chart to publication-ready, journal-quality figures in the same session.
We’ll cover this like a real classroom lesson:
- the two main systems (base vs ggplot2)
- when to use which
- step-by-step examples you can copy-paste right now
- common customizations
- saving high-quality files
- modern 2026 workflow
1. Two Plotting Worlds in R (2026 Perspective)
| System | Package | First impression | Best for | Learning investment | Final look (default) | Community dominance 2026 |
|---|---|---|---|---|---|---|
| Base R | graphics | Very fast | Quick exploration, diagnostic plots, teaching | Low | Classic / dated | ~20–30 % |
| ggplot2 | ggplot2 | Takes 5–10 min | Almost everything else: reports, papers, blogs, dashboards | Medium → high payoff | Modern, clean, professional | ~70–80 % |
Short rule of thumb most people follow in 2026:
- plot(), hist(), boxplot() → quick look in console
- everything you want to show to others → ggplot2
2. Base R Plotting – Fast & Always Available
No installation needed — these are built-in.
Quick scatter plot
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# Classic iris example plot(iris$Sepal.Length, iris$Petal.Length, pch = 16, # filled circle col = iris$Species, # color by species cex = 1.4, # point size main = "Iris – Sepal vs Petal Length (Base R)", xlab = "Sepal Length (cm)", ylab = "Petal Length (cm)") # Add legend manually legend("topleft", legend = levels(iris$Species), col = 1:3, pch = 16, bty = "n") # no box around legend |
Histogram + density
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
hist(iris$Sepal.Width, breaks = 25, col = "lightblue", border = "white", main = "Sepal Width Distribution", xlab = "Width (cm)") # Overlay density curve lines(density(iris$Sepal.Width), col = "darkblue", lwd = 2) |
Boxplot by group
|
0 1 2 3 4 5 6 7 8 9 10 |
boxplot(Petal.Length ~ Species, data = iris, col = c("lightpink", "lightgreen", "lightyellow"), main = "Petal Length by Species", ylab = "Length (cm)", notch = TRUE) # notches show confidence around median |
3. ggplot2 Plotting – The Modern Professional Standard
Install once (if not already):
|
0 1 2 3 4 5 6 |
install.packages("ggplot2") # or install.packages("tidyverse") |
Basic philosophy (very important to remember)
A ggplot is built in layers:
- data + mapping (aes()) → what goes where
- geoms → how to draw (points, lines, bars…)
- scales → colors, axes, legends
- facets → small multiples
- themes → overall look
- labs() → titles, labels
Classic scatter plot (compare to base)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
library(ggplot2) ggplot(iris, aes(x = Sepal.Length, y = Petal.Length, color = Species)) + geom_point(size = 3, alpha = 0.85, pch = 16) + geom_smooth(method = "loess", se = TRUE, alpha = 0.15) + # smooth trend + CI scale_color_brewer(palette = "Dark2") + labs( title = "Iris Dataset – Sepal vs Petal Length", subtitle = "Colored by species with LOESS smoother", x = "Sepal Length (cm)", y = "Petal Length (cm)", color = "Species" ) + theme_minimal(base_size = 14) + theme(legend.position = "bottom") |
Bar plot with Hyderabad flavor
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# Fake data – average monthly electricity bill Hyderabad areas df <- data.frame( area = c("Gachibowli", "Hitech City", "Banjara Hills", "Kukatpally", "Uppal"), avg_bill = c(4850, 6200, 7800, 4100, 5300) ) ggplot(df, aes(x = reorder(area, avg_bill), y = avg_bill, fill = avg_bill)) + geom_col() + geom_text(aes(label = paste("₹", avg_bill)), vjust = -0.4, fontface = "bold") + scale_fill_gradient(low = "lightyellow", high = "darkred") + labs( title = "Average Monthly Electricity Bill – Hyderabad Areas (2026)", x = NULL, y = "Average Bill (₹)" ) + theme_minimal() + theme(axis.text.x = element_text(angle = 30, hjust = 1)) |
Faceted plot (small multiples – very powerful)
|
0 1 2 3 4 5 6 7 8 9 10 11 |
ggplot(iris, aes(Sepal.Length, Sepal.Width, color = Species)) + geom_point(size = 2.5) + geom_smooth(method = "lm", se = FALSE) + facet_wrap(~ Species, ncol = 3) + theme_light() + labs(title = "Sepal Dimensions by Species") |
4. Saving Plots (Very Important for Reports)
Base R
|
0 1 2 3 4 5 6 7 8 |
png("my_plot.png", width = 800, height = 600, res = 120) plot(...) # your plot code dev.off() |
ggplot2 – preferred ways
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
# High-resolution PNG ggsave("iris_scatter.png", width = 8, height = 6, dpi = 300) # Vector PDF (best for publications) ggsave("iris_scatter.pdf", width = 7, height = 5) # Change size / quality ggsave("iris_big.png", width = 10, height = 7, dpi = 600, bg = "white") |
5. Quick 2026 Workflow Recommendation
- Explore fast → base R (plot(), hist(), boxplot())
- Polish for sharing → ggplot2
- Combine multiple plots → use patchwork package
|
0 1 2 3 4 5 6 7 8 9 10 11 12 |
# install.packages("patchwork") library(patchwork) p1 <- ggplot(iris, aes(Species, Sepal.Length)) + geom_boxplot() p2 <- ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) + geom_point() p1 + p2 # side by side |
- Make interactive (bonus) → plotly::ggplotly(p) or ggiraph
Your Turn – Mini Practice
Copy and run this block — then try changing colors, themes, adding facets:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
library(ggplot2) ggplot(iris, aes(x = Petal.Length, y = Petal.Width, color = Species, shape = Species)) + geom_point(size = 3.5, alpha = 0.9) + scale_color_brewer(palette = "Set2") + scale_shape_manual(values = c(16, 17, 15)) + labs( title = "Iris Petal Dimensions", subtitle = "2026 – classic dataset still beautiful", x = "Petal Length (cm)", y = "Petal Width (cm)" ) + theme_bw(base_size = 14) + theme(legend.position = "bottom", plot.title = element_text(face = "bold")) |
Want to go deeper?
- Specific ggplot2 topics (themes, scales, annotations, facets)?
- Saving publication-ready figures (CMYK, high-res)?
- Combining base + ggplot in one report?
- Or next topic (dplyr data wrangling before plotting)?
Just say — next lesson is ready! 📊✨🚀
