order() keeps records together; which.max is a position
◈ 8 cardsorders[order(-orders$amount), ] sorts the whole frame, 1005 first; order(orders$prov, -orders$amount) sorts by two keys. sort(orders$amount) sorts the column alone and breaks the records. max() is a value, 1320; which.max() is a position, 5; orders$prov[which.max(orders$amount)] is "AB". unique() lists distinct values; length(unique(x)) counts them.
Sorting a frame is sorting its rows
Module 6 warned about the spreadsheet disaster: sorting one column while the others stay put, so amounts no longer belong to their orders. R has the same trap with a different name. sort() sorts one vector:
> sort(orders$amount)
[1] 90 180 215 250 305 420 470 510 640 760 980 1320
Use that as a column and every amount sits beside the wrong order. To sort the frame, use order(), which returns the row positions in sorted order, and put it in the rows slot:
> order(-orders$amount)
[1] 5 10 3 8 6 12 1 9 4 11 2 7
> orders[order(-orders$amount), ]
order_id prov channel amount units order_date
5 1005 AB Online 1320 8 2025-02-03
10 1010 AB Store 980 6 2025-03-11
3 1003 ON Store 760 5 2025-01-15
(twelve rows; three shown). The minus sign gives descending — decreasing = TRUE also works. The row names travel with their rows: 5, 10, 3.
Worked example — two keys
Province A→Z, then amount high→low inside each province — the Sheets Sort range → add another sort column:
> orders[order(orders$prov, -orders$amount), ]
order_id prov channel amount units order_date
5 1005 AB Online 1320 8 2025-02-03
10 1010 AB Store 980 6 2025-03-11
8 1008 BC Store 640 4 2025-02-27
12 1012 BC Online 470 3 2025-03-25
4 1004 BC Online 250 2 2025-01-21
3 1003 ON Store 760 5 2025-01-15
The first key groups; the second key orders within the group. head(orders[order(-orders$amount), ], 3) is the top-3 list.
Finding the largest: value or position?
> max(orders$amount)
[1] 1320
> which.max(orders$amount)
[1] 5
> orders$prov[which.max(orders$amount)]
[1] "AB"
max() is the value. which.max() is the position of that value — row 5 — and a position is what you index with: the province of the largest order is orders$prov[5], "AB", and its id is orders$order_id[5], 1005. This is INDEX/MATCH with MAX in Sheets, in two functions. which.min() is 7 (the amount > 900) lists every position that passes, 5 10`.
Distinct values
> unique(orders$prov)
[1] "ON" "QC" "BC" "AB"
> length(unique(orders$prov))
[1] 4
unique() returns each value once, in order of first appearance — not sorted. length() of it is the number of distinct values, Sheets' COUNTA(UNIQUE(B2:B13)).
Type the two-key sort and the lookup, then fill the worksheet
The worksheet asks for max() and which.max() of the amounts — one is a value and one is a position, and the quiz swaps them.
CRISP-DM: sorting and finding are data understanding → explore data.