R Programming Quiz: Formula Syntax
10 questions · exam conditions
0:00
Formula SyntaxQuestion 1 of 10

The variable group is a factor with levels A, B, and C, and x is numeric. An analyst fits lm(y ~ 0 + group + x, data = d).

Which description best characterizes the model columns generated by this formula under ordinary R contrast handling?

One intercept, two group contrast columns, and one column for x.
Three group indicator columns and one column for x, with no intercept.
Two group contrast columns and three group-specific columns for x, with no intercept.
One group indicator column and one column for x, with the other groups omitted.
← Back to quizzes

R Programming Quiz

R Programming Quiz: Formula Syntax

Practice Formula Syntax in R Programming with focused quiz questions that help you check what you know, review explanations, and build confidence with test-style prompts.

What this quiz covers

This quiz focuses on Formula Syntax, giving you a quick way to practice the rules, question types, and explanations that matter most for R Programming.

How to use this quiz

Try each quiz question before looking at the correct answer. Use the explanations to review missed ideas, then come back to similar questions until the pattern feels familiar.

All questions

Question 1

The variable group is a factor with levels A, B, and C, and x is numeric. An analyst fits lm(y ~ 0 + group + x, data = d).

Which description best characterizes the model columns generated by this formula under ordinary R contrast handling?

  1. One intercept, two group contrast columns, and one column for x.
  2. Three group indicator columns and one column for x, with no intercept. (correct answer)
  3. Two group contrast columns and three group-specific columns for x, with no intercept.
  4. One group indicator column and one column for x, with the other groups omitted.
Explanation: When you see a formula with 0 + (or equivalently - 1) in R, your first instinct should be: the intercept has been suppressed. This fundamentally changes how R encodes factor variables in the design matrix. Normally, R uses treatment contrasts for factors — one reference level is absorbed into the intercept, and the remaining levels become deviation columns. But when you remove the intercept with 0 +, R has no baseline to absorb, so it expands each factor level into its own full indicator (dummy) column. For a three-level factor like group with levels A, B, and C, that means three separate 0/1 columns — one for each level. The numeric variable x then contributes a single column as usual, giving you four total columns: groupA, groupB, groupC, and x. That's exactly what B describes. A is wrong because it describes the default intercept parameterization — one intercept plus two contrast columns — which is what you'd get with lm(y ~ group + x), not lm(y ~ 0 + group + x). C is wrong on two counts: it incorrectly implies three separate slopes for x (that would require an interaction term like group:x), and its column count doesn't match the formula. D is a misunderstanding of how R handles factors; no levels are "omitted" here — suppressing the intercept adds a column rather than removing one. A helpful rule of thumb: 0 + with a factor trades one intercept for one extra group column, giving you full-rank indicator encoding instead of contrast encoding.

Question 2

For each dose, a data frame contains the number of successes in wins and the number of failures in losses. An analyst fits glm(cbind(wins, losses) ~ dose, family = binomial, data = d).

How is the left side of this formula interpreted by the binomial model?

  1. As two unrelated continuous responses fitted simultaneously with a shared slope.
  2. As two predictor columns, with dose treated as the model response.
  3. As the numeric ratio wins / losses, computed before the model is fitted.
  4. As a success-count and failure-count response for each observation. (correct answer)
Explanation: When you see cbind() on the left side of a glm formula with family = binomial, your brain should immediately shift into "grouped binomial" mode. This is R's way of supplying both pieces of binomial trial information — how many times you succeeded and how many times you failed — for each row of data. In this setup, cbind(wins, losses) creates a two-column matrix where each row encodes a complete binomial experiment: wins gives the number of successes and losses gives the number of failures. R interprets this as a response with n=wins+lossesn = \text{wins} + \text{losses} trials and k=winsk = \text{wins} successes per observation. The model then estimates the log-odds of winning as a function of dose. That's exactly what D describes — a success-count and failure-count response — making it the correct answer. A is wrong because cbind() here defines a single response (a binomial outcome), not two separate continuous responses being modeled simultaneously. B has the relationship completely backwards: dose is the predictor on the right side of ~, not the response. C is a tempting trap — you might think R quietly computes wins / losses as a ratio before fitting, but it doesn't. R retains the raw counts so it knows the total number of trials, which is essential for correct likelihood computation. A pre-computed ratio would discard that information entirely. The pattern to remember: cbind(successes, failures) on the left of a binomial glm formula always means "grouped binary data," not a ratio, not dual responses, and not swapped roles.

Question 3

An analyst models event counts using glm(count ~ temperature + offset(log(exposure)), family = poisson, data = d). Assume the usual log link.

Which statement correctly describes the role of exposure in this model?

  1. Its logged value enters the linear predictor with its coefficient fixed at 11, adjusting for differing observation periods. (correct answer)
  2. Its logged value is included as an ordinary predictor whose coefficient is estimated alongside the temperature effect.
  3. It replaces count as the effective response after the model internally converts raw counts to rates.
  4. It causes both temperature and exposure to be log-transformed before the model is fitted.
Explanation: Whenever you see offset(...) in a glm() call, the key question to ask is: how does this term enter the linear predictor, and is its coefficient estimated or fixed? In a Poisson model with log link, the linear predictor takes the form log(μ)=β0+β1temperature+log(exposure)\log(\mu) = \beta_0 + \beta_1 \cdot \text{temperature} + \log(\text{exposure}). The offset() wrapper forces the coefficient on log(exposure)\log(\text{exposure}) to equal exactly 11 — it is not estimated from the data. This means the model is effectively modeling the rate μ/exposure\mu / \text{exposure}, while still treating raw counts as the response. This is answer A, which correctly states that the logged exposure enters the linear predictor with its coefficient fixed at 11, adjusting for unequal observation windows or population sizes. B is wrong because it describes an ordinary covariate — if you simply wrote + log(exposure) without offset(), R would estimate a free coefficient for it, which is a meaningfully different model. C is wrong because the response remains the raw count; the model does not internally replace it. The rate interpretation is a consequence of the offset algebra, not a literal transformation of the response variable. D is wrong because offset() only affects exposure — it computes log(exposure)\log(\text{exposure}) and fixes its coefficient. temperature is left completely untouched and enters the model on its original scale. A useful rule of thumb: offset() = "include this log-transformed variable but don't estimate its slope — assume it equals 1." Any time you see it, think rate adjustment, not free parameter estimation.

Question 4

A model is first fitted with fit <- lm(log(y) ~ x * g, data = d). It is then modified using update(fit, . ~ . - x:g + z).

Which formula describes the updated model?

  1. log(y) ~ x * g + z, because the right-side dot prevents terms from being removed.
  2. y ~ x + g + z, because the left-side dot restores the untransformed response.
  3. log(y) ~ z, because removing x:g also removes its component main effects.
  4. log(y) ~ x + g + z, preserving the response and removing only the interaction. (correct answer)
Explanation: When working with update() in R, think of the dot (.) as a placeholder meaning "whatever was already there." The syntax . ~ . means "keep the left-hand side as-is, keep the right-hand side as-is, then apply modifications." Understanding this placeholder behavior is the key to this question. In the original model, the formula is log(y) ~ x * g, which R expands internally to log(y) ~ x + g + x:g. When you call update(fit, . ~ . - x:g + z), the left dot preserves log(y), the right dot preserves x + g + x:g, then -x:g removes only the interaction term, and +z adds the new predictor. The result is log(y) ~ x + g + z, making D the correct answer. A is wrong because it claims the dot prevents term removal — the opposite is true. The dot expands the existing formula first, and then modifications like -x:g are applied on top of it. B is wrong on two counts: the left-side dot does not strip transformations — it preserves log(y) exactly. There is no mechanism in update() that restores an untransformed response. C reflects a common misunderstanding about how R handles hierarchy. Removing x:g with -x:g targets only the interaction term, not its component main effects x and g. Those remain in the model unless you explicitly remove them with -x -g. As a study tip, remember: update() modifies, never resets. The dot is a copy, and each +/- term is a surgical edit on that copy.

Question 5

Several sites each contain blocks. Block labels such as 1 and 2 are reused at different sites, so a block is meaningful only within its site. An analyst writes response ~ site / block.

How does R expand the right side of this formula?

  1. site + block, treating site and block as crossed main effects.
  2. site + site:block, representing blocks nested within sites. (correct answer)
  3. block + site:block, retaining a global block effect but omitting site.
  4. site * block, including both main effects and their crossed interaction.
Explanation: When you see the / operator in an R formula, think "nesting." The slash is shorthand for a specific hierarchical relationship: the term on the right is nested within the term on the left, meaning the right-side grouping only makes sense in the context of the left-side grouping. This is exactly the scenario described — block labels repeat across sites, so blocks have no global meaning on their own. R expands site / block as site + site:block. The site term captures the main effect of each site, and site:block captures the interaction of site with block — which effectively defines unique blocks within each site. This makes B the correct answer. The expansion correctly accounts for the fact that "block 1 at site A" and "block 1 at site B" are completely different experimental units. A is wrong because site + block treats block as a global, crossed main effect — as if block labels were consistent and meaningful across all sites. That's the opposite of a nested structure. C is wrong for a similar reason: retaining a standalone block term implies blocks exist independently of sites, which contradicts the nested design and also drops the site main effect entirely. D is wrong because site * block expands to site + block + site:block, which again includes a global block main effect that's meaningless when block labels are reused across sites. A useful memory trick: read / as "within" — a / b means "b within a," which R translates to a + a:b. Whenever block or group labels are reused across higher-level units, nesting with / is almost certainly what you need.

Question 6

An analyst wants an ordinary linear model whose model matrix contains one raw column for x and one raw column containing the numerical square of x.

Which formula most directly specifies the intended model?

  1. y ~ x + x^2, because the ^ operator inside a formula numerically squares x and adds it as a distinct column.
  2. y ~ x + I($x^2$), because I() protects arithmetic inside the formula from special formula interpretation. (correct answer)
  3. y ~ x + x:x, because a variable interacting with itself produces a squared column in the model matrix.
  4. y ~ poly(x, 2), because it returns exactly two raw polynomial columns corresponding to x and x^2.
Explanation: When writing formulas in R, you need to understand that operators like +, *, :, and ^ have special formula meanings that differ from their arithmetic meanings. The formula language uses these symbols to describe model structure, not math — so x^2 doesn't mean "x squared"; it means "x crossed with itself up to degree 2," which R interprets as just x alone. The I() function — standing for "as-Is" — is R's escape hatch. Anything inside I() is evaluated as pure arithmetic, bypassing formula interpretation entirely. So I($x^2$) genuinely computes the square of each value of x and hands that numeric vector to the model matrix as a distinct column. Writing y ~ x + I($x^2$) gives you exactly two raw columns: one for x and one for x2x^2. That makes B the correct answer. A fails because inside a formula, x^2 uses the crossing operator ^, which expands interactions up to degree 2 — but since there's only one variable, it simply returns x. No squared column is added; you get the same model as y ~ x. C is also wrong: x:x is the interaction of x with itself, which R reduces to just x again. An interaction of identical terms doesn't produce a power. D is tempting but incorrect. poly(x, 2) by default returns orthogonal polynomials, not raw xx and x2x^2 columns. You'd need poly(x, 2, raw = TRUE) for raw columns. Study tip: Whenever you need arithmetic inside a formula, reach for I(). Think of it as "I mean this mathematically."

Question 7

A linear model is fitted with lm(y ~ x1 * x2, data = d). The estimated coefficient of x1 is 22, and the estimated coefficient of x1:x2 is 0.5-0.5. Both predictors are numeric.

Holding x2 at 44, what change in the fitted response is associated with a one-unit increase in x1?

  1. The fitted response increases by 22 units.
  2. The fitted response decreases by 0.50.5 units.
  3. The fitted response does not change. (correct answer)
  4. The fitted response increases by 44 units.
Explanation: When a model includes an interaction term like x1 * x2, the effect of x1 on the response is no longer a single fixed number — it depends on the value of x2. Specifically, the marginal effect of x1 is βx1+βx1:x2x2\beta_{x1} + \beta_{x1:x2} \cdot x2. This is the core concept being tested here. Plugging in the given values, the effect of a one-unit increase in x1 when x2 = 4 is 2+(0.5)(4)=22=02 + (-0.5)(4) = 2 - 2 = 0. The fitted response does not change — making C the correct answer. A is tempting because 22 is literally the coefficient printed next to x1 in the model summary. But that coefficient only represents the effect of x1 when x2 = 0, not at arbitrary values of x2. Using it directly here ignores the interaction entirely. B mistakes the interaction coefficient 0.5-0.5 for the total effect of x1. The interaction coefficient alone tells you nothing about the marginal effect of x1; it only scales how that effect changes across values of x2. D arrives at 44 — the value of x2 itself — with no clear mathematical basis. It likely reflects confusion about what role x2 = 4 plays in the calculation. As a study tip: whenever you see an interaction term, immediately rewrite the marginal effect formula before plugging in numbers. Writing out y^x1=βx1+βx1:x2x2\frac{\partial \hat{y}}{\partial x1} = \beta_{x1} + \beta_{x1:x2} \cdot x2 explicitly will prevent you from mistakenly reading the coefficient table at face value.

Question 8

A data frame d contains columns y, x, z, and w. A separate object named q also exists in the calling environment. The model is fitted with lm(y ~ . - z, data = d).

Which variables are used as predictors by this model?

  1. Only x and w; y, z, and the external object q are not predictors. (correct answer)
  2. x, w, and q; the dot includes objects from the calling environment.
  3. y, x, and w; subtracting z leaves every other data-frame column.
  4. Only x; the dot selects the first remaining predictor after z is removed.
Explanation: When you see a formula like y ~ . - z in R's lm(), you need to understand exactly what the dot (.) means and where it looks for variables. The dot is shorthand for "all variables in the data argument," not all objects in your R environment. This is a critical scoping distinction. In lm(y ~ . - z, data = d), the dot expands to every column in d except the response variable y. That gives you x, z, and w. Then - z removes z from the predictor set. The result is that only x and w serve as predictors — making A the correct answer. The external object q is never considered because the dot is bounded by data = d. B is wrong because it assumes the dot reaches into the calling environment to find q. It does not — the dot is strictly scoped to the data frame supplied to data. C is wrong because it includes y as a predictor. y appears on the left side of the ~, designating it as the response, so it is automatically excluded when the dot expands. D is wrong because the dot selects all remaining columns, not just one. There is no rule that selects only the "first" predictor. A useful rule of thumb: always mentally substitute the dot with "all columns in the data frame," then apply any subtractions. Never let the dot cross the boundary of the data argument — outside variables simply don't exist to the formula.

Question 9

An experiment records a numeric response for each combination of the factors treatment and site. The analyst wants treatment differences to be allowed to vary by site, while retaining the overall main effects of both factors.

Which formula specifies that structure most directly?

  1. y ~ treatment + site, which includes both main effects but no interaction.
  2. y ~ treatment:site, which includes only the joint interaction terms.
  3. y ~ treatment * site, which includes both main effects and their interaction. (correct answer)
  4. y ~ treatment / site, which treats site as nested within treatment.
Explanation: When building regression formulas in R, your goal is to match the model structure to the research question. Here, the analyst wants treatment differences to vary by site — that's the definition of an interaction — while still keeping both main effects in the model. That combination points directly to the * operator. In R, y ~ treatment * site expands to y ~ treatment + site + treatment:site, giving you the main effect of treatment, the main effect of site, and their interaction term. This lets the effect of treatment differ across sites while still estimating each factor's overall contribution — exactly what the passage describes. Choice A (y ~ treatment + site) is the additive model. It assumes treatment differences are constant across every site, which contradicts the requirement that those differences be allowed to vary. Choice B (y ~ treatment:site) includes only the interaction term and drops both main effects entirely — statistically unusual and rarely what you want, since you lose the interpretable baseline effects of each factor. Choice D (y ~ treatment / site) uses nesting notation, which expands to treatment + treatment:site; it models site within treatment levels and omits site's independent main effect, which misrepresents the structure described. Choice C is correct because * is R's shorthand for "main effects plus their interaction," matching the analyst's goal precisely. A handy rule: memorize the three interaction operators — + (additive only), : (interaction only), and * (both main effects and interaction). On exam questions involving factorial designs, ask yourself whether the research question demands varying effects across groups; if yes, you almost certainly need *.

Question 10

The predictors a, b, and c are entered into a model using y ~ (a + b + c)^2 - a:b.

Ignoring the implicit intercept, which set of terms remains after R expands the formula?

  1. The three main effects plus a:c and b:c, but neither a:b nor a:b:c. (correct answer)
  2. The three main effects plus all three pairwise interactions and the three-way interaction.
  3. Only a:c and b:c, because raising the parenthesized expression removes main effects.
  4. The three main effects plus a:b:c, because subtracting a:b promotes the higher-order term.
Explanation: When reading R model formulas, you need to understand two rules: the ^n operator expands all interactions up to order n, and subtracting a term (e.g., -a:b) explicitly removes it from the expanded result — it does not trigger any promotion or cascading effects. Starting with (a + b + c)^2, R expands this into all main effects plus all pairwise interactions: a, b, c, a:b, a:c, and b:c. Notice that ^2 caps expansion at two-way interactions, so a:b:c is never generated in the first place. Then -a:b simply removes a:b from that list, leaving you with the three main effects plus a:c and b:c. That's exactly what answer A describes, making it correct. Answer B is wrong because ^2 limits expansion to interactions of order two or less — the three-way interaction a:b:c is never included, regardless of whether you subtract anything afterward. Answer C reflects a misunderstanding of how parentheses work in R formulas; (a + b + c)^2 does not strip main effects. The ^ operator means "expand to this interaction depth," and main effects are always retained unless you explicitly remove them with something like -a. Answer D introduces the fictional idea that subtracting a lower-order term "promotes" a higher-order term — R has no such behavior. Subtraction is purely a removal operation. A handy rule to remember: in R formulas, ^n adds terms up to order n, and -term removes exactly that term. Neither operation causes cascading changes to other terms in the model.