Many base R functions accept a formula. In score ~ group, the left side is summarized separately for each right-side group.

Program

Play the script to add a selected bonus, then summarize scores by group with formula syntax.

bonus
aggregate_formula.R
Replay: real traced execution (multi-file project)
scores <- data.frame(group = c("A", "A", "B", "B"), score = c(8, 10, 6, 12))
bonus <- 0
scores$score <- scores$score + bonus
summary <- aggregate(score ~ group, data = scores, FUN = mean)
label <- paste(summary$group, summary$score, collapse = "; ")
cat(label, "\n", sep = "")
scores <- data.frame(group = c("A", "A", "B", "B"), score = c(8, 10, 6, 12))
bonus <- 1
scores$score <- scores$score + bonus
summary <- aggregate(score ~ group, data = scores, FUN = mean)
label <- paste(summary$group, summary$score, collapse = "; ")
cat(label, "\n", sep = "")
scores <- data.frame(group = c("A", "A", "B", "B"), score = c(8, 10, 6, 12))
bonus <- 2
scores$score <- scores$score + bonus
summary <- aggregate(score ~ group, data = scores, FUN = mean)
label <- paste(summary$group, summary$score, collapse = "; ")
cat(label, "\n", sep = "")
  1. scores ← 4 rows x 2 cols

    1scores <- data.frame(group = c("A", "A", "B", "B"), score = c(8, 10, 6, 12))2bonus <- 0
    values this step4 rows x 2 colsscores
  2. bonus ← 0

    1scores <- data.frame(group = c("A", "A", "B", "B"), score = c(8, 10, 6, 12))2bonus <- 03scores$score <- scores$score + bonus
    values this step0bonus
  3. scores$score <- scores$score + bonus

    2bonus <- 03scores$score <- scores$score + bonus4summary <- aggregate(score ~ group, data = scores, FUN = mean)
    values this step8, 10, 6, 12scores$score0bonus
  4. summary ← 2 rows x 2 cols

    3scores$score <- scores$score + bonus4summary <- aggregate(score ~ group, data = scores, FUN = mean)5label <- paste(summary$group, summary$score, collapse = "; ")
    values this step2 rows x 2 colssummarygrouped scoresscoresscore ~ groupformula
  5. label ← A 9; B 9

    4summary <- aggregate(score ~ group, data = scores, FUN = mean)5label <- paste(summary$group, summary$score, collapse = "; ")6cat(label, "\n", sep = "")
    values this stepA 9; B 9labelA 9; B 9summary
  6. cat(label, " ", sep = "")

    5label <- paste(summary$group, summary$score, collapse = "; ")6cat(label, "\n", sep = "")
    outputA 9; B 9
    values this stepA 9; B 9label
  1. scores ← 4 rows x 2 cols

    1scores <- data.frame(group = c("A", "A", "B", "B"), score = c(8, 10, 6, 12))2bonus <- 1
    values this step4 rows x 2 colsscores
  2. bonus ← 1

    1scores <- data.frame(group = c("A", "A", "B", "B"), score = c(8, 10, 6, 12))2bonus <- 13scores$score <- scores$score + bonus
    values this step1bonus
  3. scores$score ← 9, 11, 7, 13

    2bonus <- 13scores$score <- scores$score + bonus4summary <- aggregate(score ~ group, data = scores, FUN = mean)
    values this step8, 10, 6, 12 9, 11, 7, 13scores$score1bonus
  4. summary ← 2 rows x 2 cols

    3scores$score <- scores$score + bonus4summary <- aggregate(score ~ group, data = scores, FUN = mean)5label <- paste(summary$group, summary$score, collapse = "; ")
    values this step2 rows x 2 colssummarygrouped scoresscoresscore ~ groupformula
  5. label ← A 10; B 10

    4summary <- aggregate(score ~ group, data = scores, FUN = mean)5label <- paste(summary$group, summary$score, collapse = "; ")6cat(label, "\n", sep = "")
    values this stepA 10; B 10labelA 10; B 10summary
  6. cat(label, " ", sep = "")

    5label <- paste(summary$group, summary$score, collapse = "; ")6cat(label, "\n", sep = "")
    outputA 10; B 10
    values this stepA 10; B 10label
  1. scores ← 4 rows x 2 cols

    1scores <- data.frame(group = c("A", "A", "B", "B"), score = c(8, 10, 6, 12))2bonus <- 2
    values this step4 rows x 2 colsscores
  2. bonus ← 2

    1scores <- data.frame(group = c("A", "A", "B", "B"), score = c(8, 10, 6, 12))2bonus <- 23scores$score <- scores$score + bonus
    values this step2bonus
  3. scores$score ← 10, 12, 8, 14

    2bonus <- 23scores$score <- scores$score + bonus4summary <- aggregate(score ~ group, data = scores, FUN = mean)
    values this step8, 10, 6, 12 10, 12, 8, 14scores$score2bonus
  4. summary ← 2 rows x 2 cols

    3scores$score <- scores$score + bonus4summary <- aggregate(score ~ group, data = scores, FUN = mean)5label <- paste(summary$group, summary$score, collapse = "; ")
    values this step2 rows x 2 colssummarygrouped scoresscoresscore ~ groupformula
  5. label ← A 11; B 11

    4summary <- aggregate(score ~ group, data = scores, FUN = mean)5label <- paste(summary$group, summary$score, collapse = "; ")6cat(label, "\n", sep = "")
    values this stepA 11; B 11labelA 11; B 11summary
  6. cat(label, " ", sep = "")

    5label <- paste(summary$group, summary$score, collapse = "; ")6cat(label, "\n", sep = "")
    outputA 11; B 11
    values this stepA 11; B 11label
formula `score ~ group` reads as summarize `score` by `group`.
aggregate `aggregate(formula, data, FUN)` applies a summary to each group.
data argument `data = scores` tells R where to find the formula names.