Memra

One category → Rows; two → Rows × Columns; "for only…" → Filter

◈ 7 cards

Translate the question: the thing you want per goes in Rows, a second "by" goes in Columns, the measure with its function in Values, "for only" in Filters. In R, a second grouping is + in the formula.

Reading a question for its layout

The paper does not ask you to build a pivot. It gives a business question and four layouts, and asks which one answers it. Every such question has the same anatomy, and each part maps to one zone:

  • "per province", "by channel", "for each month" → a categorical in Rows (the first) or Columns (the second).
  • "total amount", "average order", "how many orders" → the measure in Values with the function the verb names: total = Sum, average = Average, how many = Count.
  • "for only the online orders", "in Q1 alone" → the field in Filters.

Worked example — four questions

Average order amount per province, by channel, for Q1 only. Per province → prov in Rows. By channel → channel in Columns. Average amount → amount in Values, function Average. For Q1 only → order_date in Filters, set to January–March. Reading the result: the ON × Online cell is 465, the ON × Store cell 532.5.

Total units per channel. One categorical → channel in Rows; units in Values, Sum: Online 21, Store 20.

How many orders per province? prov in Rows and — the part people miss — a field to count. Any field will do, but the natural one is the identifier: order_id in Values with the function Count: AB 2, BC 3, ON 4, QC 3. Sum of order_id would add the identifiers up (a meaningless number, Lesson 2.3), and Sum of amount answers a different question.

Orders from AB only, by channel. "From AB only" → prov in Filters, set to AB; channel in Rows; amount in Values, Sum: Online 1320, Store 980.

The standing trap is the first one: swapping Rows and Values. A layout with amount in Rows and prov in Values gives twelve rows labelled 90, 180, 215 … with a count of provinces beside each — a table, but not an answer.

The R side: a second grouping is +

A second categorical joins the right-hand side of the formula with +:

> aggregate(amount ~ prov + channel, data = orders, FUN = mean)
  prov channel amount
1   AB  Online 1320.0
2   BC  Online  360.0
3   ON  Online  465.0
4   QC  Online   90.0
5   AB   Store  980.0
6   BC   Store  640.0
7   ON   Store  532.5
8   QC   Store  197.5

The same eight cells as the Rows × Columns pivot — but laid out long, one row per combination, not as a grid. Lesson 7.4's xtabs() gives the grid. The Q1 filter is a subset() before the aggregate: aggregate(amount ~ prov + channel, data = subset(orders, order_date < "2025-04-01"), FUN = mean). And "how many" is FUN = length: aggregate(order_id ~ prov, data = orders, FUN = length) prints 2, 3, 4, 3.

Type one, then choose four layouts

Type the two-factor aggregate. Each question gives a business question and four layouts.

CRISP-DM: choosing the layout is data understanding → explore data; the question it answers is business understanding written down first.

questionRowsColumnsValues(function)Filtersaverage amountper province,by channel, Q1onlyprovchannelamount(Average)order_datetotal unitsper channelchannelunits (Sum)how manyorders perprovinceprovorder_id(Count)orders from ABonly, bychannelchannelamount (Sum)prov = ABR: aggregate(amount ~ prov + channel, data = orders, FUN = mean) — a second grouping joins with +; afilter is a subset() first.
Question → layout. "Per" and "by" name the categoricals, the verb names the function, "for only" names the filter.
NORMAL ~/memra/learn/afm-112/choosing-the-pivot-layout utf-8 LF