Why did the eighth verb take minutes, when the first one took a chapter? You have met eight verbs now, and a handful of small words that traveled between them: by, where, as, all_but, descending. This chapter is about those small words, and it is the shortest useful thing in the book. The answer to the question above is that the small words never changed.
Each of them means one thing. Not one thing per verb, one thing. When you meet a verb you have never seen, the small words in it already make sense. That is most of what makes this grammar quick to get back after a year away.
9.1by says which rows go together
You saw by on summarize, where it made the groups. It is the same word on add, where it says which rows a value is worked out within. It is the same word again on take, where it says which rows the first few are taken from.
run(' sales then summarize [total] as total([revenue]) by [product]')
product
total
Doohickey
400
Gadget
720
Sprocket
240
Widget
700
sales |>summarize(total =total(revenue), by = product)
product
total
Doohickey
400
Gadget
720
Sprocket
240
Widget
700
sales >> summarize(total = total(col.revenue), by = col.product)
product
total
Doohickey
400
Gadget
720
Sprocket
240
Widget
700
sales then summarize [total] as total([revenue]) by [product]
On add, the same word turns a collapse into a broadcast. The aggregation is still worked out per group, and instead of one row per group, every row gets its group’s answer, which is exactly what a share needs:
Read a product’s rows and their shares sum to one: each row’s revenue over its own group’s total. In dplyr this idiom needs a grouped mutate and an ungroup, and in SQL it needs a window function. Here it is the by you already know, sitting on a different verb. And on take, the word means the same thing a third time:
run(' sales then sort [revenue] descending then take 1 by [product]')
date
region
product
quantity
revenue
cost
2026-01-26
West
Gadget
5
300
200
2026-01-09
East
Widget
8
200
80
2026-03-03
East
Doohickey
5
200
125
2026-06-19
East
Sprocket
10
150
120
sales |>sort(descending(revenue)) |>take(1, by = product)
date
region
product
quantity
revenue
cost
2026-01-26
West
Gadget
5
300
200
2026-01-09
East
Widget
8
200
80
2026-03-03
East
Doohickey
5
200
125
2026-06-19
East
Sprocket
10
150
120
sales >> sort(descending(col.revenue)) >> take(1, by = col.product)
date
region
product
quantity
revenue
cost
2026-01-26
West
Gadget
5
300
200
2026-01-09
East
Widget
8
200
80
2026-03-03
East
Doohickey
5
200
125
2026-06-19
East
Sprocket
10
150
120
Three verbs, one word, one meaning. Later you will meet by on join and on widen, and it will mean the same thing there: the columns that say which rows correspond.
9.2as gives something a name
add [name] as [value]. The name goes first, the way assignment reads, and the same shape names the result of rename and the filler in fill_missing.
It is a modifier on a column, in a position where an ordering is being given. So it reads the same on sort and inside rank, and beyond the column it marks, it has no options of its own on either.
On keep the question is about a row. Later you will see it on pick, where the question is about a column, and the difference is written down rather than guessed. Inside pick you say name or kind to name what you are asking about.
A word that travels still has a boundary, and the boundary is stated rather than guessed. by means per group, and sort already orders every row, so the word has nothing to add there and is refused by name. The sentence below is the text form, so the call is the same string in both tabs:
Error:
!
illegal: `sort` does not take the word `by`. Write `sort [column]`, and `descending` after it to run the other way
|
1 | sales then sort by [region]
| ^^
try: run('sales then sort by [region]')except GodError as refusal:print(refusal)
illegal: `sort` does not take the word `by`. Write `sort [column]`, and `descending` after it to run the other way
|
1 | sales then sort by [region]
| ^^
The message says what sort does take, which is the whole of it.
9.7 Why this matters more than it looks
A vocabulary is easy to learn and easy to lose. What survives a year away is not the word list. It is the rules for putting words together, and those only survive if there are few of them and they have no exceptions.
So the test this grammar sets itself is not whether it has a word for everything. It is whether a word you learned in one place still means the same thing in the next place you meet it. Every part after this one is that test being run. And you now hold the working form of the preface’s motto. If you can say something two ways in this grammar, one of them is a bug, and the author wants to hear about it. That sentence is not rhetoric. It is the standard each of the last seven chapters answered to, from the missing ascending to the missing drop. It is falsifiable by any reader with an afternoon.
The eight verbs and five small words you now have are the everyday core of the grammar, and the preface’s promise has reached its first checkpoint. Day one was reading, and you have been reading since the first pipeline. Day two is writing, and the practice pair ahead closes with it. Those two chapters are where this part’s claims stop being the book’s and start being yours.