Data Visualization Exercises in R: 50 Practice Problems

Fifty practice problems on data visualization in R: chart types, customization, themes, multi-plot composition, and publication-ready output. Hidden solutions.

RRun this once before any exercise
library(ggplot2) library(dplyr) library(scales) library(tibble) library(forcats)

  

Section 1. Chart types (12 problems)

Exercise 1.1: Scatter plot

Difficulty: Beginner. mpg vs wt.

Show solution
RInteractive R
ggplot(mtcars, aes(wt, mpg)) + geom_point()

  

Exercise 1.2: Bar chart of counts

Difficulty: Beginner.

Show solution
RInteractive R
ggplot(diamonds, aes(cut)) + geom_bar()

  

Exercise 1.3: Bar with explicit heights (geom_col)

Difficulty: Intermediate.

Show solution
RInteractive R
counts <- diamonds |> count(cut) ggplot(counts, aes(cut, n)) + geom_col()

  

Exercise 1.4: Histogram

Difficulty: Beginner.

Show solution
RInteractive R
ggplot(diamonds, aes(price)) + geom_histogram(bins = 30)

  

Exercise 1.5: Density

Difficulty: Intermediate.

Show solution
RInteractive R
ggplot(iris, aes(Sepal.Length, fill = Species)) + geom_density(alpha = 0.5)

  

Exercise 1.6: Box plot per group

Difficulty: Beginner.

Show solution
RInteractive R
ggplot(iris, aes(Species, Sepal.Length)) + geom_boxplot()

  

Exercise 1.7: Violin

Difficulty: Intermediate.

Show solution
RInteractive R
ggplot(iris, aes(Species, Sepal.Length)) + geom_violin()

  

Exercise 1.8: Line chart

Difficulty: Intermediate.

Show solution
RInteractive R
ggplot(economics, aes(date, unemploy)) + geom_line()

  

Exercise 1.9: Area chart

Difficulty: Intermediate.

Show solution
RInteractive R
ggplot(economics, aes(date, unemploy)) + geom_area(fill = "steelblue", alpha = 0.5)

  

Exercise 1.10: Heatmap (geom_tile)

Difficulty: Advanced.

Show solution
RInteractive R
df <- expand.grid(x = 1:5, y = 1:5) df$z <- runif(nrow(df)) ggplot(df, aes(x, y, fill = z)) + geom_tile()

  

Exercise 1.11: Pie chart (via coord_polar)

Difficulty: Advanced.

Show solution
RInteractive R
ggplot(diamonds, aes("", fill = cut)) + geom_bar(width = 1) + coord_polar("y")

  

Exercise 1.12: 2D density

Difficulty: Advanced.

Show solution
RInteractive R
ggplot(diamonds, aes(carat, price)) + geom_density_2d()

  

Section 2. Aesthetics & mapping (8 problems)

Exercise 2.1: Color by group

Difficulty: Beginner.

Show solution
RInteractive R
ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) + geom_point()

  

Exercise 2.2: Size by continuous

Difficulty: Beginner.

Show solution
RInteractive R
ggplot(mtcars, aes(wt, mpg, size = hp)) + geom_point()

  

Exercise 2.3: Shape by category

Difficulty: Intermediate.

Show solution
RInteractive R
ggplot(iris, aes(Sepal.Length, Petal.Length, shape = Species)) + geom_point(size = 3)

  

Exercise 2.4: Color vs fill on bars

Difficulty: Intermediate.

Show solution
RInteractive R
ggplot(diamonds, aes(cut, fill = clarity)) + geom_bar(color = "black")

  

Exercise 2.5: Alpha for overlap

Difficulty: Intermediate.

Show solution
RInteractive R
ggplot(diamonds, aes(carat, price)) + geom_point(alpha = 0.05)

  

Exercise 2.6: Group line by id

Difficulty: Intermediate.

Show solution
RInteractive R
ggplot(ChickWeight, aes(Time, weight, group = Chick)) + geom_line(alpha = 0.4)

  

Exercise 2.7: Multiple aesthetics

Difficulty: Advanced.

Show solution
RInteractive R
ggplot(mtcars, aes(wt, mpg, color = factor(cyl), size = hp, shape = factor(am))) + geom_point(alpha = 0.7)

  

Exercise 2.8: Constant outside aes

Difficulty: Advanced.

Show solution
RInteractive R
ggplot(mtcars, aes(wt, mpg)) + geom_point(color = "red", size = 3)

  

Section 3. Customization (10 problems)

Exercise 3.1: Title + subtitle + caption

Difficulty: Beginner.

Show solution
RInteractive R
ggplot(mtcars, aes(wt, mpg)) + geom_point() + labs(title = "Weight vs MPG", subtitle = "Motor Trend 1974", caption = "Source: mtcars")

  

Exercise 3.2: Axis labels

Difficulty: Beginner.

Show solution
RInteractive R
ggplot(mtcars, aes(wt, mpg)) + geom_point() + labs(x = "Weight (1000 lbs)", y = "Miles per gallon")

  

Exercise 3.3: Format y as currency

Difficulty: Intermediate.

Show solution
RInteractive R
ggplot(diamonds, aes(carat, price)) + geom_point(alpha = 0.05) + scale_y_continuous(labels = dollar_format())

  

Exercise 3.4: Log axis

Difficulty: Intermediate.

Show solution
RInteractive R
ggplot(diamonds, aes(carat, price)) + geom_point(alpha = 0.05) + scale_x_log10() + scale_y_log10()

  

Exercise 3.5: Manual color

Difficulty: Intermediate.

Show solution
RInteractive R
ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) + geom_point() + scale_color_manual(values = c(setosa = "red", versicolor = "blue", virginica = "green"))

  

Exercise 3.6: ColorBrewer

Difficulty: Intermediate.

Show solution
RInteractive R
ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) + geom_point() + scale_color_brewer(palette = "Set2")

  

Exercise 3.7: Viridis

Difficulty: Intermediate.

Show solution
RInteractive R
ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) + geom_point() + scale_color_viridis_d()

  

Exercise 3.8: Reorder x by frequency

Difficulty: Intermediate.

Show solution
RInteractive R
ggplot(diamonds, aes(forcats::fct_infreq(cut))) + geom_bar()

  

Exercise 3.9: Coord flip

Difficulty: Beginner.

Show solution
RInteractive R
ggplot(diamonds, aes(cut)) + geom_bar() + coord_flip()

  

Exercise 3.10: Zoom without filtering

Difficulty: Advanced.

Show solution
RInteractive R
ggplot(mtcars, aes(wt, mpg)) + geom_point() + coord_cartesian(ylim = c(15, 30))

  

Section 4. Themes (8 problems)

Exercise 4.1: theme_minimal

Difficulty: Beginner.

Show solution
RInteractive R
ggplot(mtcars, aes(wt, mpg)) + geom_point() + theme_minimal()

  

Exercise 4.2: theme_bw

Difficulty: Beginner.

Show solution
RInteractive R
ggplot(mtcars, aes(wt, mpg)) + geom_point() + theme_bw()

  

Exercise 4.3: Rotate x text

Difficulty: Intermediate.

Show solution
RInteractive R
ggplot(diamonds, aes(clarity)) + geom_bar() + theme(axis.text.x = element_text(angle = 45, hjust = 1))

  

Exercise 4.4: Bottom legend

Difficulty: Beginner.

Show solution
RInteractive R
ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) + geom_point() + theme(legend.position = "bottom")

  

Exercise 4.5: Remove legend

Difficulty: Beginner.

Show solution
RInteractive R
ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) + geom_point() + theme(legend.position = "none")

  

Exercise 4.6: Bold centered title

Difficulty: Intermediate.

Show solution
RInteractive R
ggplot(mtcars, aes(wt, mpg)) + geom_point() + labs(title = "Title") + theme(plot.title = element_text(face = "bold", hjust = 0.5))

  

Exercise 4.7: Remove minor gridlines

Difficulty: Intermediate.

Show solution
RInteractive R
ggplot(mtcars, aes(wt, mpg)) + geom_point() + theme(panel.grid.minor = element_blank())

  

Exercise 4.8: Custom theme function

Difficulty: Advanced.

Show solution
RInteractive R
my_theme <- function() theme_minimal() + theme(plot.title = element_text(face = "bold")) ggplot(mtcars, aes(wt, mpg)) + geom_point() + labs(title = "Demo") + my_theme()

  

Section 5. Multi-plot & faceting (6 problems)

Exercise 5.1: facet_wrap

Difficulty: Beginner.

Show solution
RInteractive R
ggplot(iris, aes(Sepal.Length, Petal.Length)) + geom_point() + facet_wrap(~ Species)

  

Exercise 5.2: facet_grid

Difficulty: Intermediate.

Show solution
RInteractive R
ggplot(diamonds, aes(carat, price)) + geom_point(alpha = 0.1) + facet_grid(cut ~ clarity)

  

Exercise 5.3: Free scales

Difficulty: Intermediate.

Show solution
RInteractive R
ggplot(mpg, aes(displ, hwy)) + geom_point() + facet_wrap(~ drv, scales = "free_y")

  

Exercise 5.4: patchwork side by side

Difficulty: Intermediate.

Show solution
RInteractive R
library(patchwork) p1 <- ggplot(mtcars, aes(wt, mpg)) + geom_point() p2 <- ggplot(mtcars, aes(hp, mpg)) + geom_point() p1 | p2

  

Exercise 5.5: patchwork two-by-two

Difficulty: Intermediate.

Show solution
RInteractive R
library(patchwork) p1 <- ggplot(mtcars, aes(wt, mpg)) + geom_point() p2 <- ggplot(mtcars, aes(hp, mpg)) + geom_point() p3 <- ggplot(mtcars, aes(disp, mpg)) + geom_point() p4 <- ggplot(mtcars, aes(qsec, mpg)) + geom_point() (p1 | p2) / (p3 | p4)

  

Exercise 5.6: Custom facet labels

Difficulty: Advanced.

Show solution
RInteractive R
ggplot(mtcars, aes(wt, mpg)) + geom_point() + facet_wrap(~ cyl, labeller = labeller(cyl = c(`4` = "4-cyl", `6` = "6-cyl", `8` = "8-cyl")))

  

Section 6. Publication & save (6 problems)

Exercise 6.1: ggsave PNG

Difficulty: Beginner.

Show solution
RInteractive R
p <- ggplot(mtcars, aes(wt, mpg)) + geom_point() ggsave("plot.png", p, width = 6, height = 4, dpi = 300)

  

Exercise 6.2: ggsave PDF

Difficulty: Beginner.

Show solution
RInteractive R
p <- ggplot(mtcars, aes(wt, mpg)) + geom_point() ggsave("plot.pdf", p, width = 6, height = 4)

  

Exercise 6.3: Annotate threshold line

Difficulty: Intermediate.

Show solution
RInteractive R
ggplot(mtcars, aes(wt, mpg)) + geom_point() + geom_hline(yintercept = mean(mtcars$mpg), linetype = "dashed", color = "red")

  

Exercise 6.4: Annotate text

Difficulty: Intermediate.

Show solution
RInteractive R
ggplot(mtcars, aes(wt, mpg)) + geom_point() + annotate("text", x = 4, y = 30, label = "Outlier zone", color = "red")

  

Exercise 6.5: Highlight region

Difficulty: Advanced.

Show solution
RInteractive R
ggplot(mtcars, aes(wt, mpg)) + annotate("rect", xmin = -Inf, xmax = Inf, ymin = 25, ymax = Inf, fill = "lightgreen", alpha = 0.3) + geom_point()

  

Exercise 6.6: Publication-ready ensemble

Difficulty: Advanced.

Show solution
RInteractive R
ggplot(diamonds |> sample_n(2000), aes(carat, price, color = cut)) + geom_point(alpha = 0.6) + scale_y_continuous(labels = dollar_format()) + scale_color_brewer(palette = "Set2") + labs(title = "Diamond price vs carat", subtitle = "Sample of 2000", x = "Carat", y = "Price", color = "Cut") + theme_minimal() + theme(plot.title = element_text(face = "bold"), legend.position = "bottom")

  

What to do next

  • ggplot2-Exercises (shipped), depth on every geom and scale.
  • EDA-Exercises (shipped), viz inside the analysis loop.