---
title: "Tutorial 1: R Basics and tidyverse"
subtitle: "assemblykor - Korean National Assembly Data for Political Science Education"
output: learnr::tutorial
runtime: shiny_prerendered
---

```{r setup, include=FALSE}
library(learnr)
library(assemblykor)
library(dplyr)
knitr::opts_chunk$set(warning = FALSE, message = FALSE)
data(legislators)
data(bills)
data(wealth)
tutorial_options(exercise.eval = FALSE)
```

```{r theme, echo=FALSE}
htmltools::includeCSS(
  system.file("tutorials/css/assemblykor.css", package = "assemblykor")
)
```

## Learning Objectives

**Research Question**: How has the composition of the Korean National Assembly changed?

In this tutorial, you will explore data on 947 legislators across the 20th-22nd assemblies while learning essential R tools.

You will learn:

- Loading and inspecting data in R
- 5 core `dplyr` functions: `filter()`, `select()`, `mutate()`, `arrange()`, `summarise()`
- Connecting analysis steps with the pipe operator (`%>%`)
- Joining two datasets together

## 1. Loading Data

```{r load-data, exercise=TRUE}
library(assemblykor)
library(dplyr)

data(legislators)
dim(legislators)
```

### Inspecting Data Structure

Always check the structure first. This is the most important first step.

```{r str-data, exercise=TRUE}
str(legislators)
```

947 rows, 15 columns. Each row = one legislator's record in one assembly term. The same legislator serving in both the 20th and 21st assemblies appears as two rows.

### Key Variables

| Variable | Description | Example |
|----------|-------------|---------|
| `member_id` | Unique legislator ID | Same across terms |
| `assembly` | Assembly number | 20, 21, 22 |
| `name` | Name (Korean) | |
| `party` | Party affiliation | |
| `district_type` | Election type | constituency, proportional |
| `gender` | Gender | M, F |
| `seniority` | Terms elected | 1 = freshman |
| `n_bills` | Total bills (lead + co-sponsored) | Median ~700 |
| `n_bills_lead` | **Lead-sponsored** bills only | Median ~56 |

> **Note**: `n_bills` includes both lead and co-sponsorship. Korean legislators actively co-sponsor, so some have thousands. Use `n_bills_lead` for bills the legislator personally led.

```{r explore-head, exercise=TRUE}
head(legislators)
```

```{r explore-summary, exercise=TRUE}
summary(legislators[, c("assembly", "seniority", "n_bills_lead")])
```

```{r quiz-nrow, echo=FALSE}
quiz(
  question("There are 661 unique legislators but 947 rows. Why?",
    answer("Some rows have missing data that got split into separate entries"),
    answer("Some legislators served in multiple assemblies, appearing once per term", correct = TRUE),
    answer("The dataset includes both legislators and their staff members"),
    answer("There are duplicates from merging multiple source databases"),
    correct = "Correct! A legislator serving in both the 20th and 21st assemblies appears as two separate rows."
  )
)
```

## 2. filter(): Selecting Rows

`filter()` selects rows that meet specified conditions.

**Syntax**: `filter(data, condition1, condition2, ...)`

Multiple conditions separated by commas are combined with AND.

```{r filter-demo, exercise=TRUE}
# 22nd assembly female legislators only
women_22 <- filter(legislators, assembly == 22, gender == "F")
nrow(women_22)
```

### Common Comparison Operators

| Operator | Meaning | Example |
|----------|---------|---------|
| `==` | Equal | `assembly == 22` |
| `!=` | Not equal | `party != "independent"` |
| `>`, `>=` | Greater | `seniority >= 3` |
| `<`, `<=` | Less | `n_bills_lead < 10` |
| `%in%` | In a set | `party %in% c("A", "B")` |

Try finding **22nd assembly freshmen** (seniority == 1):

```{r filter-ex, exercise=TRUE, exercise.blanks="___"}
freshmen <- filter(legislators, ___, ___)
nrow(freshmen)
```

```{r filter-ex-hint}
freshmen <- filter(legislators, assembly == 22, seniority == 1)
nrow(freshmen)
```

## 3. select(): Choosing Columns

```{r select-demo, exercise=TRUE}
legislators %>%
  filter(assembly == 22) %>%
  select(name, party, n_bills_lead) %>%
  head(10)
```

The `%>%` (pipe) connects operations: "take data, THEN filter, THEN select columns, THEN show first 10."

```{r select-patterns, exercise=TRUE}
# Select columns starting with "n_"
legislators %>%
  select(name, starts_with("n_")) %>%
  head(5)
```

## 4. The Pipe Operator `%>%`

The pipe passes the result on the left as the **first argument** to the function on the right.

Without pipe (hard to read):

```{r pipe-without, exercise=TRUE}
# Must read from inside out
head(select(filter(legislators, assembly == 22), name, party), 5)
```

With pipe (natural reading order):

```{r pipe-with, exercise=TRUE}
legislators %>%
  filter(assembly == 22) %>%
  select(name, party) %>%
  head(5)
```

> **Tip**: In RStudio, `Ctrl+Shift+M` (Mac: `Cmd+Shift+M`) inserts the pipe.

## 5. mutate(): Creating New Variables

```{r mutate-demo, exercise=TRUE}
legislators %>%
  mutate(
    n_cosponsor = n_bills - n_bills_lead,
    lead_ratio  = round(n_bills_lead / n_bills, 3)
  ) %>%
  filter(assembly == 22) %>%
  select(name, party, n_bills_lead, n_cosponsor, lead_ratio) %>%
  arrange(desc(lead_ratio)) %>%
  head(10)
```

## 6. arrange(): Sorting

```{r arrange-demo, exercise=TRUE}
legislators %>%
  filter(assembly == 22) %>%
  arrange(desc(n_bills_lead)) %>%
  select(name, party, district_type, seniority, n_bills_lead) %>%
  head(10)
```

## 7. group_by() + summarise()

This is the most powerful `dplyr` pattern. Group data and compute summaries per group.

```{r group-demo, exercise=TRUE}
legislators %>%
  group_by(assembly) %>%
  summarise(
    total       = n(),
    n_women     = sum(gender == "F"),
    pct_women   = round(n_women / total * 100, 1),
    avg_senior  = round(mean(seniority, na.rm = TRUE), 1),
    median_bills = median(n_bills_lead)
  )
```

### Party Comparison

```{r group-party, exercise=TRUE}
legislators %>%
  filter(assembly == 22) %>%
  group_by(party) %>%
  summarise(
    n          = n(),
    pct_women  = round(sum(gender == "F") / n() * 100, 1),
    avg_bills  = round(mean(n_bills_lead), 1)
  ) %>%
  filter(n >= 5) %>%
  arrange(desc(n))
```

Calculate female legislator proportion by assembly:

```{r group-ex, exercise=TRUE, exercise.blanks="___"}
legislators %>%
  group_by(___) %>%
  summarise(
    total = n(),
    n_women = sum(___ == "F"),
    pct_women = round(n_women / total * 100, 1)
  )
```

```{r group-ex-hint}
legislators %>%
  group_by(assembly) %>%
  summarise(
    total = n(),
    n_women = sum(gender == "F"),
    pct_women = round(n_women / total * 100, 1)
  )
```

```{r quiz-group, echo=FALSE}
quiz(
  question("You want to calculate the median number of bills for each party. Which approach works?",
    answer("filter(legislators, party) %>% median(n_bills_lead)"),
    answer("legislators %>% group_by(party) %>% summarise(med = median(n_bills_lead))", correct = TRUE),
    answer("legislators %>% mutate(med = median(n_bills_lead))"),
    answer("legislators %>% arrange(party, n_bills_lead)"),
    correct = "Correct! group_by() splits by party, then summarise() computes the median within each group."
  )
)
```

## 8. Exploring Other Datasets

```{r bills-explore, exercise=TRUE}
data(bills)
dim(bills)
head(bills %>% select(bill_name, committee, propose_date, result), 5)
```

```{r bills-result, exercise=TRUE}
bills %>%
  count(result, sort = TRUE) %>%
  head(8)
```

```{r wealth-explore, exercise=TRUE}
data(wealth)
dim(wealth)
summary(wealth$net_worth / 1e6)
```

> **Units**: The `wealth` data uses **thousands of KRW** (1,000 won). Divide by 1e6 to get billions of KRW.

## 9. Joining Two Datasets

Join links datasets by a common key column.

| Function | Description |
|----------|-------------|
| `inner_join()` | Keep only matching rows |
| `left_join()` | Keep all rows from left |
| `full_join()` | Keep all rows from both |

```{r join-demo, exercise=TRUE}
leg_wealth <- legislators %>%
  filter(assembly == 22) %>%
  inner_join(
    wealth %>% filter(year == 2024),
    by = "member_id"
  )

cat("After join:", nrow(leg_wealth), "rows\n")
cat("Original 22nd:", nrow(filter(legislators, assembly == 22)), "rows\n")
```

```{r join-analysis, exercise=TRUE}
leg_wealth <- legislators %>%
  filter(assembly == 22) %>%
  inner_join(wealth %>% filter(year == 2024), by = "member_id")

leg_wealth %>%
  group_by(gender) %>%
  summarise(
    n = n(),
    median_nw_bn = round(median(net_worth / 1e6, na.rm = TRUE), 1)
  )
```

## Summary

| Function | Purpose | Analogy |
|----------|---------|---------|
| `filter()` | Select rows | Excel filter |
| `select()` | Select columns | Keep relevant columns |
| `mutate()` | Add new columns | Calculated field |
| `arrange()` | Sort | Ascending/descending |
| `group_by() + summarise()` | Group summary | Pivot table |
| `%>%` (pipe) | Connect steps | "and then" |
| `inner_join()` | Merge data | VLOOKUP |

## Exercises

### Exercise 1: Proportional Representatives

How many proportional representatives (`district_type == "proportional"`) are in the 22nd Assembly?

```{r ex1, exercise=TRUE}

```

```{r ex1-solution}
legislators %>%
  filter(assembly == 22, district_type == "proportional") %>%
  nrow()
```

### Exercise 2: Freshman Ratio

Calculate the proportion of freshmen (`seniority == 1`) by assembly.

```{r ex2, exercise=TRUE}

```

```{r ex2-solution}
legislators %>%
  group_by(assembly) %>%
  summarise(
    total = n(),
    freshmen = sum(seniority == 1, na.rm = TRUE),
    pct = round(freshmen / total * 100, 1)
  )
```

### Exercise 3: Bill Results

Calculate the number of bills and the rate of original passage by assembly. Note: the result values are in Korean. Use `result == "\uc6d0\uc548\uac00\uacb0"` (original passage).

```{r ex3, exercise=TRUE}

```

```{r ex3-solution}
bills %>%
  group_by(assembly) %>%
  summarise(
    n_bills = n(),
    n_passed = sum(result == "\uc6d0\uc548\uac00\uacb0", na.rm = TRUE),
    pass_rate = round(n_passed / n_bills * 100, 1)
  )
```

### Exercise 4: Wealth and Legislation

Find the correlation between lead-sponsored bills (`n_bills_lead`) and net worth. You need to join two datasets first.

```{r ex4, exercise=TRUE}

```

```{r ex4-solution}
merged <- legislators %>%
  filter(assembly == 22) %>%
  inner_join(wealth %>% filter(year == 2024), by = "member_id")

cor(merged$n_bills_lead, merged$net_worth, use = "complete.obs")
```

### Exercise 5: District Type Comparison

Design an analysis comparing constituency vs proportional legislators' activity patterns. Choose at least 3 metrics.

```{r ex5, exercise=TRUE}

```

```{r ex5-hint}
legislators %>%
  filter(assembly == 22) %>%
  group_by(district_type) %>%
  summarise(
    n = n(),
    median_lead = median(n_bills_lead),
    median_total = median(n_bills),
    pct_women = round(sum(gender == "F") / n() * 100, 1),
    avg_seniority = round(mean(seniority, na.rm = TRUE), 1)
  )
```
