---
title: "Data Visualization — In-Class Code"
author: "Data Skills for Psychology"
date: today
format:
  html:
    toc: true
    toc-depth: 2
    theme: cosmo
    code-overflow: wrap
    df-print: kable
---

## Setup

```{r}
#| message: false
library(tidyverse)   # readr, dplyr, ggplot2, etc.
library(patchwork)   # combine plots side-by-side
library(ggthemes)    # extra themes
```

Load the World Bank Poverty and Inequality Platform data:

```{r}
#| message: true
pip <- read_csv("https://raw.githubusercontent.com/PsyTeachR/ads-v3/refs/heads/master/data/pip_gini_welfare_2010.csv")
```

## The Grammar of Graphics

### Set a default theme

```{r}
theme_set(theme_bw())   # applies to every plot you make
```

## Building a Plot, Layer by Layer

### Layer 1: A blank plot

```{r}
ggplot(data = pip)
```

### Layer 2: Mapping variables

```{r}
ggplot(data = pip,
       mapping = aes(x = gini, y = welfare_mean))
```

In practice, almost everyone drops the argument names:

```{r}
ggplot(pip, aes(x = gini, y = welfare_mean))
```

### Layer 3: Add a geom

```{r}
ggplot(pip, aes(x = gini, y = welfare_mean)) +
  geom_point()
```

### Multiple geoms

```{r}
# boxplot with points on top
ggplot(pip, aes(x = region_name, y = welfare_mean)) +
  geom_boxplot(width = .2) +
  geom_jitter(width = .2) +
  coord_flip()
```

```{r}
# points behind the boxplot
ggplot(pip, aes(x = region_name, y = welfare_mean)) +
  geom_jitter(width = .2) +
  geom_boxplot(width = .2) +
  coord_flip()
```

### Activity: Your first plot

1.  Load the `pip` data with `read_csv()` (see the Setup section).
2.  Run `theme_set(theme_bw())`.
3.  Make a scatterplot of `gini` on x and `welfare_mean` on y. Which geom should you use?
4.  **Bonus**: Add a second geom — `geom_smooth(method = "lm", formula = y ~ x)` — to show a trendline.

```{r}
# Your code here:

```

## Styling Geoms

### Styling the whole geom

```{r}
ggplot(pip, aes(x = gini, y = welfare_mean)) +
  geom_point(colour = "dodgerblue",
             alpha = 0.2,      # 20% transparency
             shape = 18,       # solid diamond
             size = 2) +
  geom_smooth(method = lm,
              formula = y ~ x,
              colour = "navy",
              linetype = 3)    # dotted line
```

### Style by category

```{r}
# colour points by region
ggplot(pip, aes(x = gini, y = welfare_mean,
                colour = region_code)) +
  geom_point(alpha = 0.6)
```

## Picking the Right Plot

### Counting categories: geom_bar()

```{r}
ggplot(pip, aes(x = region_code)) +
  geom_bar()
```

Add `fill` inside `aes()` to colour bars by category:

```{r}
ggplot(pip, aes(x = region_code, fill = region_code)) +
  geom_bar()
```

### geom_col() for pre-computed counts

```{r}
count_data <- count(pip, region_code, sort = TRUE)

ggplot(count_data, aes(x = region_code, y = n)) +
  geom_col()
```

Use `fct_reorder()` to sort bars by size:

```{r}
ggplot(count_data,
       aes(x = fct_reorder(region_code, n), y = n)) +
  geom_col() +
  labs(x = "Region")
```

## One Continuous Variable

### Histograms

```{r}
ggplot(pip, aes(x = welfare_mean)) +
  geom_histogram(binwidth = 5, boundary = 0,
                 fill = "white", color = "black")
```

### Grouped continuous: violin plot

```{r}
ggplot(pip, aes(x = region_code, y = welfare_mean)) +
  geom_violin(scale = "width")
```

### Grouped continuous: boxplot

```{r}
ggplot(pip, aes(x = region_code, y = welfare_mean)) +
  geom_boxplot()
```

### Combo: violin + boxplot + mean

```{r}
ggplot(pip, aes(x = region_code, y = welfare_mean,
                fill = region_code)) +
  geom_violin(alpha = 0.4, scale = "width") +
  geom_boxplot(width = 0.25, fill = "white",
               alpha = 0.75, outlier.alpha = 0) +
  stat_summary(fun = mean, geom = "point",
               size = 2, shape = 18) +
  guides(fill = "none") +
  labs(x = "Region", y = "Mean Welfare per Capita")
```

### Activity: Compare distributions

Using the `pip` data:

1.  Make a **histogram** of `gini` (binwidth around 0.02 is a reasonable start).
2.  Make a **violin plot** of `gini` by `region_code`.
3.  Make a **boxplot** of the same thing.
4.  **Bonus**: Which plot best shows that some regions have narrow inequality distributions while others are broad?

```{r}
# Your code here:

```

## Two Continuous Variables

### Scatterplot

```{r}
ggplot(pip, aes(x = gini, y = welfare_mean)) +
  geom_point()
```

### Adding a trendline

```{r}
ggplot(pip, aes(x = gini, y = welfare_mean)) +
  geom_point(alpha = 0.2) +
  geom_smooth(method = lm, formula = y ~ x)   # linear
```

## Axes and Scales

### Axis limits

```{r}
ggplot(pip, aes(x = gini, y = welfare_mean)) +
  geom_point(alpha = 0.2) +
  coord_cartesian(ylim = c(0, 100))
```

## Themes and Labels

### Built-in themes

```{r}
ggplot(pip, aes(x = gini, y = welfare_mean)) +
  geom_point(alpha = 0.2) +
  theme_light(base_size = 11)   # font size in points
```

### Theme tweaks

```{r}
ggplot(pip, aes(x = gini, y = welfare_mean)) +
  geom_point(alpha = 0.2) +
  theme_light(base_size = 11) +
  theme(plot.background = element_blank())   # remove outer border
```

### Labels with labs()

```{r}
ggplot(pip, aes(x = gini, y = welfare_mean)) +
  geom_point(alpha = 0.2) +
  labs(title = "Inequality vs. welfare across regions",
       subtitle = "Data from 2010",
       x = "Gini Index",
       y = "Mean Welfare per Capita",
       caption = "Source: World Bank PIP")
```

### Activity: Style a plot

Starting from your scatterplot:

1.  Add `alpha = 0.3` to `geom_point()` so the points are transparent.
2.  Use `scale_x_continuous()` and `scale_y_continuous()` to add nicer axis labels.
3.  Apply a theme you like (try `theme_minimal()` or `theme_light()`).
4.  Use `labs()` to add a title, subtitle, and caption.
5.  **Bonus**: Colour the points by `region_code`.

```{r}
# Your code here:

```

## Saving Plots

### ggsave()

`ggsave()` saves the last plot you made by default:

```{r}
#| eval: false
ggsave("my_plot.png", width = 5, height = 7)
```

Or save a plot you stored in an object:

```{r}
#| eval: false
box <- ggplot(pip, aes(x = region_name, y = gini)) +
  geom_boxplot()

ggsave("box_plot.jpg", plot = box, width = 7, height = 7)
```

## Dealing with Overplotting

First, simulate some data with lots of overlapping points on a 1–5 rating scale:

```{r}
set.seed(8675309)   # makes the simulation reproducible

n <- 10000          # number of data points to simulate

# make a vector of one-second increments across 2025
d <- seq(as.POSIXct('2025-01-01'), as.POSIXct('2025-12-31'), by = "sec")

simdat <- tibble(
  datetime = sample(d, size = n, replace = TRUE),
  rating   = sample(1:5, n, replace = TRUE),
  mean     = 50 + month(datetime) - 6 + abs(rating - 3) * 5 - 5,
  score    = rnorm(n, mean, sd = 12)
)
```

### The problem

```{r}
ggplot(simdat, aes(x = score, y = rating)) +
  geom_point()
```

### Fix 1: jitter

```{r}
ggplot(simdat, aes(x = score, y = rating)) +
  geom_jitter(height = 0.2, width = 0, alpha = 0.1)
```

### Fix 2: facets

```{r}
ggplot(simdat, aes(x = score)) +
  geom_histogram(binwidth = 5, boundary = 0,
                 fill = "dodgerblue", color = "black") +
  facet_wrap(~ rating, ncol = 1, labeller = label_both)
```

## Putting It All Together

### A publication-ready plot

```{r}
ggplot(pip, aes(x = gini, y = welfare_mean)) +
  geom_point(colour = "dodgerblue", alpha = 0.3) +
  geom_smooth(method = lm, formula = y ~ x,
              colour = "navy", se = FALSE) +
  scale_x_continuous(name = "Gini Index",
                     breaks = seq(0, 1, .1)) +
  scale_y_continuous(name = "Mean Welfare per Capita",
                     breaks = seq(0, 100, 20)) +
  coord_cartesian(xlim = c(.2, .7), ylim = c(0, 100)) +
  theme_light(base_size = 12) +
  theme(plot.background = element_blank()) +
  labs(title = "Higher inequality, lower welfare",
       subtitle = "Countries, 2010")
```
