Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

A note on this chapter’s data. Every number you see below is computed by the R code on the page from kern_crops_sim — a simulated Kern County crop dataset (8 commodities × 9 years, 2015–2023; 72 rows). It is labeled *_sim because the real source (USDA NASS Quick Stats) needs a registered API key the automated build could not obtain. The magnitudes are realistic for a top U.S. agricultural county, but they are not measured values and carry no claim about actual Kern production (see the codebook, data/codebooks/kern_crops_sim.md). The methods you learn here are exactly the ones you would apply to the real data.

1The Kern hook: has the crop mix shifted toward nuts?

Drive any highway out of Bakersfield and you will pass mile after mile of almond and pistachio orchards. Older residents will tell you it did not always look like that — there used to be more cotton, more open field. Is that just a story, or did the mix of crops Kern County grows really change?

That question is about a categorical variable: each block of farmland is classified into a category (nuts, fruit, citrus, vegetable, field crop), and we want to know how the shares of those categories compare across time. We cannot answer it with a mean — “the average crop” is meaningless. We answer it by counting and turning counts into proportions.

Here is the hook, computed from the data, no hand-waving:

# Share of harvested acreage in each crop category, for 2015 and for 2023.
share_by_year <- function(yr) {
  d <- subset(crops, year == yr)                       # keep only that year's rows
  totals <- tapply(d$harvested_acres, d$category, sum) # acres summed within each category
  round(100 * totals / sum(totals), 2)                 # each category's percent of the year
}
share_2015 <- share_by_year(2015)
share_2023 <- share_by_year(2023)

share_2015["NUTS"]   # nuts' share of acreage in 2015 (percent)
share_2023["NUTS"]   # nuts' share of acreage in 2023 (percent)

In this dataset, nuts went from Unexecuted inline expression for: round(share_2015["NUTS"],2)% of harvested acreage in 2015 to Unexecuted inline expression for: round(share_2023["NUTS"],2)% in 2023 — an Unexecuted inline expression for: round(share_2023["NUTS"] - share_2015["NUTS"],2) percentage-point jump (every figure here is computed from kern_crops_sim; the total harvested acreage in 2023 works out to 567,407 simulated acres). The story checks out in the simulated data. By the end of this chapter you will be able to build that comparison yourself, display it honestly, and judge whether a difference in shares is large enough to call an association — meaning the two things tend to go together (we define this carefully in Section 4) — all without ever implying that growing nuts causes anything.

2Learning objectives

By the end of this chapter you will be able to:

  1. (Apply) Build frequency and relative-frequency tables for one categorical variable and interpret the proportions.

  2. (Apply) Construct two-way contingency tables and compute joint, marginal, and conditional proportions.

  3. (Apply) Create bar charts, segmented (stacked) bar charts, and mosaic plots, and read association from them.

  4. (Analyze) Judge whether two categorical variables appear associated from a two-way table and describe the direction of that association.

  5. (Communicate) Report a categorical comparison clearly without implying causation from observational data.

This chapter assumes you have worked through Chapter 1 (variables and study design) and Chapter 2 (summaries and plots for numerical data). Here we do for categorical data what Chapter 2 did for numbers.


31. Frequency tables for one categorical variable

3.1Intuition

A categorical variable records which group an observation belongs to, not how much of something it has. “Crop category” is categorical: a row is NUTS or CITRUS, never 3.7 of them. You cannot average categories, so the first summary is simply how often each category occurs — a tally.

A raw tally (a count) answers “how many?” But counts are hard to compare when totals differ. If one county reports 18 nut operations and another reports 180, the second is not necessarily “more nutty” — it might just be bigger. So we convert each count to a proportion: its share of the whole. Proportions put every category on the same 0-to-1 scale and let us compare fairly.

3.2Formula

Suppose a categorical variable has kk categories. Let nin_i be the count in category ii — the number of observations falling in that group. The total number of (non-missing) observations is

n=i=1kni.n = \sum_{i=1}^{k} n_i .

Here \sum (capital sigma) means “add up over all categories,” ii is the category index running from 1 to kk, and nn is the grand total. The proportion (relative frequency) of category ii is

pi=nin,p_i = \frac{n_i}{n},

a number between 0 and 1. The percent is just 100pi100 \, p_i. Because every observation lands in exactly one category, the proportions must add to one: i=1kpi=1\sum_{i=1}^{k} p_i = 1 (and the percents add to 100%100\%). That “adds to one” fact is your built-in error check.

3.3R

mosaic’s tally() counts how many rows fall in each category. Read ~ category as “just the category variable.” Add format = "proportion" (or format = "percent") and tally() divides by the total for you, turning the counts into shares.

# Tally the crop CATEGORY across all 72 rows (every commodity in every year).
tally(~ category, data = crops)                          # counts
tally(~ category, data = crops, format = "proportion")   # proportions

Each commodity appears once per year for nine years, so a category with two commodities (NUTS = almonds + pistachios) shows up twice as often as a category with one (VEGETABLE = carrots). That is why NUTS, FRUIT, and CITRUS each take 25% of the rows while VEGETABLE and FIELD CROP each take 12.5% — the proportions add to 100%, exactly as the formula promises.


42. Two-way tables: joint, marginal, and conditional proportions

4.1Intuition

One categorical variable tells you how the groups split. The interesting questions almost always involve two categorical variables at once: Does the crop category go together with whether the crop is high-value? To answer “do these two go together,” we cross-tabulate — count how many observations fall in each combination of categories. The result is a two-way table (also called a contingency table).

From one two-way table you can read three different kinds of proportion, and keeping them straight is the whole skill:

4.2Formula

Write OijO_{ij} for the observed count in row ii, column jj of the table. Let the row total be Ri=jOijR_i = \sum_j O_{ij} (add across a row), the column total be Cj=iOijC_j = \sum_i O_{ij} (add down a column), and the grand total be n=ijOijn = \sum_{i}\sum_{j} O_{ij} (every cell). Then:

pij=Oijnjointpi=Rin,pj=Cjnmarginalpji=OijRiconditional (column j given row i).\underbrace{p_{ij} = \frac{O_{ij}}{n}}_{\text{joint}} \qquad \underbrace{p_{i\cdot} = \frac{R_i}{n}, \quad p_{\cdot j} = \frac{C_j}{n}}_{\text{marginal}} \qquad \underbrace{p_{j \mid i} = \frac{O_{ij}}{R_i}}_{\text{conditional (column } j \text{ given row } i)} .

Each symbol: OijO_{ij} is a single cell’s count; RiR_i and CjC_j are the totals in the margins; nn is the overall total; the dot in pip_{i\cdot} means “summed over the column index.” The plain-language version of the three formulas is just three different denominators: joint divides one cell by everybody (nn), marginal divides a row/column total by everybody (nn), and conditional divides one cell by its own row (RiR_i). The conditional proportion pjip_{j\mid i} uses the row total RiR_i as its denominator, not nn — because you are asking a question within row ii only. Read pjip_{j\mid i} aloud as “the proportion in column jj given that we are in row ii” — the vertical bar “\mid” means “given,” not division. Choosing the right denominator is the entire game.

4.3R

We will cross crop category with a value tier. First we build the value tier — a crop-year is “High value” if its value_usd is at or above the dataset median, otherwise “Lower value.” This makes a clean second categorical variable.

# Median total dollar value across all 72 crop-years.
med_value <- median(~ value_usd, data = crops)

# A second categorical variable: is this crop-year at/above the median value?
# ifelse(condition, A, B) labels a row "A" when the condition is true, "B" if not.
crops$value_tier <- ifelse(crops$value_usd >= med_value,
                           "High value", "Lower value")

# Two-way contingency table: category (rows) x value tier (columns).
# Read "~ category + value_tier" as "count every combination of the two."
tab <- tally(~ category + value_tier, data = crops)
tab

Now read the three kinds of proportion off that table, one tally() call each. The joint proportions divide every cell by the grand total (all 72 crop-years):

# JOINT proportions: every cell divided by the grand total (each cell / 72).
round(tally(~ category + value_tier, data = crops, format = "proportion"), 2)

The nine cells add to 1. The NUTS / High value cell is 0.25 — a quarter of all crop-years are both nut and high-value. The marginal proportion of the value tier ignores category entirely:

# MARGINAL proportion of each value tier (ignore category).
round(tally(~ value_tier, data = crops, format = "proportion"), 2)

Overall the crop-years split 0.50 / 0.50 between the tiers — the median split forces each tier to be exactly half, a handy sanity check. Finally the conditional proportions divide within each category:

# CONDITIONAL proportions: value tier WITHIN each category.
# tally(A ~ B) reads "A given B" -- each B column sums to 1.
round(tally(value_tier ~ category, data = crops, format = "proportion"), 2)

Read this last table down each column (each category’s column sums to 1). Among the nut crop-years, 100% are high-value; among citrus, about 56%; among field crops, 0%. The conditional shares are wildly different from column to column — that difference is exactly what we mean by association, the subject of Section 4.


53. Visualizing categorical data

5.1Intuition

A table is exact; a picture is fast. Three plots cover almost every categorical display you will ever need:

Unlike a histogram, bars for categories have gaps between them and can be reordered — there is no number line underneath, so order is a choice you make to help the reader (usually largest-to-smallest).

5.2Formula

There is no new formula here — the bars are the counts nin_i and the segment heights are the conditional proportions pjip_{j\mid i} from Section 2. The only new idea is a design rule: encode the quantity in a position or length the eye can compare (bar height), and use the colorblind-safe Okabe–Ito palette so color never becomes the only signal (a WCAG-AA accessibility requirement; CLAUDE.md Part 1).

5.3R

# Acreage by category in 2023: sum the acres in each category, then draw bars.
d23 <- subset(crops, year == 2023)
acres_by_cat <- aggregate(harvested_acres ~ category, data = d23, FUN = sum)

# Order categories tallest-to-shortest so the eye reads the biggest group first.
acres_by_cat <- acres_by_cat[order(-acres_by_cat$harvested_acres), ]
acres_by_cat$category <- factor(acres_by_cat$category,
                                levels = acres_by_cat$category)

gf_col(harvested_acres ~ category, data = acres_by_cat, fill = ~ category) %>%
  gf_refine(scale_fill_manual(values = okabe_ito), guides(fill = "none")) %>%
  gf_labs(title = "2023 harvested acreage by crop category (simulated)",
          x = "Crop category", y = "Harvested acres") %>%
  gf_theme(theme_minimal(base_size = 12))
Bar chart of 2023 harvested acreage summed by crop category. The Nuts bar is by far the tallest at about 344,000 acres, followed by much shorter Fruit and Citrus bars near 80,000 acres each, then Field crop and Vegetable bars below 41,000 acres. Bars use distinct Okabe-Ito colors and are sorted from tallest to shortest.

Harvested acreage by crop category, Kern County crop-years 2023 (simulated). Nuts dominate.

# Segmented (stacked-to-100%) bar chart: value tier WITHIN each category.
# This is the picture of the conditional proportions from Section 2.
# position = "fill" makes every bar the same height (1.0), so we compare the
# *splits*, not the totals.
seg_df <- as.data.frame(tally(~ category + value_tier, data = crops))

gf_col(Freq ~ category, fill = ~ value_tier, data = seg_df,
       position = "fill", color = "white", linewidth = 0.2) %>%
  gf_refine(scale_fill_manual(values = okabe_ito[1:2], name = "Value tier")) %>%
  gf_labs(title = "Value tier within each crop category (simulated)",
          x = "Crop category", y = "Proportion of crop-years") %>%
  gf_theme(theme_minimal(base_size = 12))
A 100 percent stacked bar chart with one bar per crop category. Each bar is split into a High value segment and a Lower value segment. The Nuts bar is entirely High value; the Field crop bar is entirely Lower value; Citrus is just over half High value; Fruit is about one third High value; Vegetable is about one fifth High value. The strongly different splits show association between category and value tier. Okabe-Ito blue and orange distinguish the two tiers.

Conditional distribution of value tier within each crop category (100% segmented bars). Every nut crop-year is high-value; no field-crop year is.

The segmented bars make the association jump out: the height of the blue segment is the conditional proportion high-value, and it ranges from 100% (nuts) down to 0% (field crops). If category and value tier were unassociated, every bar would split at the same height.


64. Reading association (without claiming causation)

6.1Intuition

Two categorical variables are associated when knowing one changes the proportions you expect for the other. Operationally: compare conditional distributions. If P(High value | NUTS) differs from P(High value | CITRUS), the value tier depends on the category — they are associated. If all the conditional distributions are identical, the variables are independent (no association).

Association is not causation. In an observational dataset like this one, nobody randomly assigned crops to be nuts. A category that tends to be high-value might differ in a dozen other ways (water needs, market, acreage). Association tells you the variables travel together; it does not tell you that one makes the other happen. Saying “growing nuts causes high value” from a table like this is the single most common — and most damaging — mistake in reading categorical data.

6.2Formula

A quick numeric handle on association compares two conditional proportions. For rows aa and bb and a target column jj, the difference in conditional proportions is

pjapjb=OajRaObjRb.p_{j \mid a} - p_{j \mid b} = \frac{O_{aj}}{R_a} - \frac{O_{bj}}{R_b}.

If this difference is 0 for every pair of rows, the variables are independent. The further it is from 0, the stronger the association. (Chapter 11 turns this informal reading into a formal chi-square test; here we read it by eye and by proportion.)

6.3R

# Conditional proportion of "High value" within each category
# (each category column of this table sums to 1).
cond <- tally(value_tier ~ category, data = crops, format = "proportion")
round(cond["High value", ], 4)

The conditional proportion of high-value runs from 0.00 (field crops) to 1.00 (nuts). Those are not equal, so category and value tier are associated in this dataset. Direction: nut and citrus crop-years skew high-value; field-crop and vegetable crop-years skew lower-value. We will describe that — and stop short of saying one causes the other.


7Worked examples

Each example runs intuition \rightarrow formula \rightarrow computation \rightarrow interpretation, the same order the chapter teaches in. At least one uses the Kern crop data.

7.1Worked Example 1 — A frequency table you can defend (Kern data)

Question. In 2023, which crop commodity took the largest share of harvested acreage in this dataset, and what share was it?

Intuition. This is a one-variable frequency question, but the “frequency” we care about is acres, not rows. So we weight each commodity by its acreage, then convert to proportions.

Formula. With nin_i now the harvested acres of commodity ii and n=inin = \sum_i n_i the total acres, the share is pi=ni/np_i = n_i / n.

Computation.

d23 <- subset(crops, year == 2023)
acres <- tapply(d23$harvested_acres, d23$commodity, sum)  # acres per commodity
shares <- round(100 * acres / sum(acres), 2)
sort(shares, decreasing = TRUE)

Interpretation. Almonds led at 37.49% of 2023 harvested acreage, with pistachios second at 23.14%; together the two nut crops are 60.63% of acreage (value from kern_crops_sim). Notice this is a different table from tally(~ category) in Section 1 — there each commodity-year counted as one row (almonds were just 1/8 of the rows). Here almonds dominate because we counted acres, not rows. Same data, different unit of count, very different story — which is exactly why you always state your unit.

7.2Worked Example 2 — Joint, marginal, conditional from one table (Kern data)

Question. Using the category × value-tier table, find (a) the joint proportion of crop-years that are nuts and high-value, (b) the marginal proportion that are high-value, and (c) the conditional proportion of high-value among citrus crop-years.

Intuition. Three questions, three denominators: the whole table, a column margin, and one row.

Formula. (a) pij=Oij/np_{ij}=O_{ij}/n; (b) pj=Cj/np_{\cdot j}=C_j/n; (c) pji=Oij/Rip_{j\mid i}=O_{ij}/R_i.

Computation.

joint_nuts_high <- tally(~ category + value_tier, data = crops,
                         format = "proportion")["NUTS", "High value"]   # (a)
marg_high       <- tally(~ value_tier, data = crops,
                         format = "proportion")["High value"]           # (b)
cond_citrus     <- tally(value_tier ~ category, data = crops,
                         format = "proportion")["High value", "CITRUS"] # (c)

round(c(joint = joint_nuts_high,
        marginal = marg_high,
        conditional_citrus = cond_citrus), 4)

Interpretation. (a) 25% of all crop-years are nuts and high-value. (b) 50% of all crop-years are high-value (the median split makes this exactly half — a useful sanity check). (c) About 55.6% of citrus crop-years are high-value. The conditional value (c) exceeds the marginal value (b), so citrus skews high-value relative to the overall rate — a hint of association.

7.3Worked Example 3 — Is the crop type associated with high value? (Kern data)

Question. Collapse category into Nuts vs. Not nuts and cross it with the value tier. Are the two variables associated? Describe the direction.

Intuition. Association means the conditional distributions differ. Compare P(High value | Nuts) with P(High value | Not nuts).

Formula. Difference in conditional proportions: pHighNutspHighNot nutsp_{\text{High}\mid \text{Nuts}} - p_{\text{High}\mid \text{Not nuts}}.

Computation.

crops$is_nuts <- ifelse(crops$category == "NUTS", "Nuts", "Not nuts")
tab2 <- tally(~ is_nuts + value_tier, data = crops)
tab2

# Conditional proportion of High value within each group (each group column sums to 1).
cond2 <- tally(value_tier ~ is_nuts, data = crops, format = "proportion")["High value", ]
round(cond2, 4)
round(cond2["Nuts"] - cond2["Not nuts"], 4)

Interpretation. Among nut crop-years, 100% are high-value; among non-nut crop-years, only 33.3% are — a difference of 0.667 in conditional proportions. That is a large, clear association: in this dataset, nut crop-years are far more likely to be high-value. We describe the pattern and stop there. This is observational, simulated data — nothing here says that being a nut crop causes high value (orchard land, water, and market all differ too).

7.4Worked Example 4 — A textbook table by hand, then in R

Question. A small campus survey of 80 students asked their primary commute mode. The counts were: Car 36, Bus 20, Bike 14, Walk 10. Build the relative-frequency table and state the two most common modes’ combined share.

Intuition. Pure one-variable frequency table: divide each count by 80.

Formula. pi=ni/np_i = n_i / n with n=80n = 80.

Computation.

modes  <- c("Car", "Bus", "Bike", "Walk")
counts <- c(36, 20, 14, 10)
# The data are already counted, so we divide directly -- this is exactly the
# arithmetic a proportion table does, shown here so you can also do it by hand:
props  <- counts / sum(counts)
data.frame(mode = modes, count = counts,
           proportion = round(props, 4),
           percent = round(100 * props, 2))

# Combined share of the two most common modes:
round(sum(sort(props, decreasing = TRUE)[1:2]) * 100, 2)

Interpretation. Car (45%) and Bus (25%) are the two most common modes, a combined 70% of students. The proportions add to 1.00, confirming no student was double-counted or dropped. (This worked example uses given textbook counts, not the Kern dataset — it shows the same method on a tiny, hand-checkable table.)


8Try it — interactive practice


9Practice problems

Work each problem fully before checking the back of the book. Odd-numbered answers appear in the Answers appendix; full worked solutions are in the instructor materials. Unless a problem says otherwise, use kern_crops_sim (load it with crops <- read.csv("data/processed/kern_crops_sim.csv")).

Round proportions to 4 decimal places and percents to 2 decimal places unless told otherwise.

  1. Build a tally(~ commodity, data = crops) over all 72 rows (add format = "proportion" for shares). How many distinct commodities are there, and what proportion of rows is each? Why are all the proportions equal?

  2. Build a tally(~ category, data = crops, format = "proportion"). Which category has the largest share of rows, and what is that share?

  3. In 2023, compute each crop category’s share of harvested acreage. Which category has the largest share, and what is it (to 2 dp)?

  4. Repeat problem 3 for 2015. By how many percentage points did the NUTS share of acreage change from 2015 to 2023?

  5. Make a bar chart of 2023 harvested acreage by commodity, sorted tallest to shortest. Which two commodities top the chart?

  6. Explain in one sentence why a bar chart of categories has gaps between bars but a histogram of a numerical variable does not.

  7. Build the two-way table of category (rows) by value_tier (columns). What is the grand total, and why does it equal 72?

  8. From the table in problem 7, compute the marginal proportion of crop-years in each category. Which categories have a marginal proportion of 0.25?

  9. From the same table, compute the joint proportion of crop-years that are FRUIT and Lower value.

  10. Compute the conditional proportion of high-value crop-years within the FRUIT category. Compare it to the marginal proportion of high-value crop-years (which is 0.50). Is fruit above or below the overall rate?

  11. Using tally(value_tier ~ category, data = crops, format = "proportion"), report the conditional proportion of high-value crop-years for every category. Order the categories from most to least likely to be high-value.

  12. Compute tally(category ~ value_tier, data = crops, format = "proportion") and read off the proportion of high-value crop-years that are nuts. Explain, in words, what denominator this used and why it answers a different question than problem 11.

  13. Make a 100%-segmented bar chart of value_tier within category. Which single category’s bar is entirely one color, and what does that tell you about its conditional distribution?

  14. Define association for two categorical variables in your own words, then state whether category and value_tier are associated in this dataset and how you can tell from the conditional proportions.

  15. Collapse category into Nuts vs. Not nuts and cross it with value_tier. Report P(High value | Nuts) and P(High value | Not nuts) and their difference.

  16. Write one sentence reporting the result of problem 15 for a county agricultural newsletter — describing the association without implying that growing nuts causes high value.

  17. A survey of 200 CSUB students records class standing: Freshman 70, Sophomore 54, Junior 44, Senior 32. Build the relative-frequency table (proportion and percent). What share are upper-division (Junior + Senior)?

  18. For the survey in problem 17, draw the bar chart you would make and state why sorting the bars by class standing (Freshman \rightarrow Senior) might be preferable to sorting by frequency here.

  19. A two-way table of 150 patients cross-classifies Treatment (Drug, Placebo) with Outcome (Improved, Not improved): Drug \rightarrow 48 improved, 27 not; Placebo \rightarrow 30 improved, 45 not. Compute P(Improved | Drug) and P(Improved | Placebo). Are treatment and outcome associated?

  20. For problem 19, this was a randomized experiment. Explain why a causal conclusion (“the drug improved outcomes”) is more defensible here than for the Kern crop association in problem 15 — connecting back to Chapter 1’s distinction between observational studies and experiments.

  21. In the Kern data, build the two-way table of commodity (rows) by value_tier and find which commodity is high-value in all 9 of its crop-years.

  22. Compute the conditional distribution of category within each year-era (Early = 2015–2019, Recent = 2020–2023), counting rows. Do the category shares of rows differ across eras? (Think about why, given how the panel is built.)

  23. Sort the category proportions from problem 2 from largest to smallest and form a running (cumulative) total as you go down the list. That running total reaches 1.00 (100%) at the last category. Explain what the running total at the second category represents.

  24. A classmate claims “since NUTS is 25% of the rows and 60.63% of 2023 acres, the table in Section 1 is wrong.” Resolve the apparent contradiction in two sentences.

  25. Communication. In one short paragraph, describe the 2023 crop-category acreage picture (from problem 3) to a Bakersfield city-council member who has not taken statistics. Use at least one proportion, name your unit of count, and avoid any causal language.


10Chapter summary

11FAQ

Q1. When is a variable “categorical” rather than numerical? If its values are labels of groups you cannot meaningfully average, it is categorical (crop category, commute mode, class standing). If its values are amounts you can add and average, it is numerical (acres, dollars). Numbers used as labels — like ZIP codes — are categorical despite looking numeric.

Q2. Proportion, percent, or count — which should I report? Report counts so readers know the sample size, and proportions/percents so they can compare. A percent with no count behind it (“70% preferred it!” — out of how many, 10 people?) is a red flag. Best practice shows both.

Q3. What’s the difference between a joint and a conditional proportion again? Joint divides by the grand total (share of everything). Conditional divides by a row or column total (share within a given group). “25% of crop-years are nuts-and-high-value” is joint; “100% of nut crop-years are high-value” is conditional. Different denominators, different meanings.

Q4. My segmented bars are all the same height — did I do something wrong? That depends on the kind. If you used position = "fill", every bar is height 1.0 (100%) by design — you are comparing the splits, not the totals. If you want to compare totals too, use position = "stack" (raw counts) or show a plain bar chart of the margins alongside.

Q5. Can a two-way table ever prove causation? Not on its own. A table shows association. Causation needs either a randomized experiment (where treatment is assigned, ruling out confounders — Chapter 1) or strong additional assumptions. From observational data, the honest verb is “is associated with,” never “causes.”

Q6. Why does this chapter use simulated data? The real Kern crop figures live behind a USDA NASS API key the automated build could not register (a human credential). Rather than invent numbers — which this project forbids — we generated a clearly labeled *_sim dataset with realistic magnitudes and a committed generator. Every method transfers unchanged to the real data once the key is in hand.

Q7. How do I decide the order of categories in a table or bar chart? For unordered (nominal) categories like crop type, sort by frequency (largest first) so the eye reads the most important group first. For ordered (ordinal) categories like class standing or a Likert scale, keep the natural order (Freshman \rightarrow Senior) so the progression is visible — even if it isn’t the frequency order.


Glossary terms introduced in this chapter are collected in book/ch03/_glossary.md and merged into the book-wide Glossary by the appendix finalizer. Odd-numbered answers are in book/ch03/_answers.md (\rightarrow Answers).

12Resumen en español