What this quiz covers
This quiz focuses on Faceting, giving you a quick way to practice the rules, question types, and explanations that matter most for R Programming.
A data frame contains observations from three sites. At each site, both Control and Treatment observations are present, and each site–treatment subset has enough observations to fit a linear model.
What does the following code fit?
ggplot(df, aes(x, y, color = treatment)) +
geom_smooth(method = "lm", se = FALSE) +
facet_wrap(vars(site))
R Programming Quiz
Practice Faceting in R Programming with focused quiz questions that help you check what you know, review explanations, and build confidence with test-style prompts.
This quiz focuses on Faceting, giving you a quick way to practice the rules, question types, and explanations that matter most for R Programming.
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.
A data frame contains observations from three sites. At each site, both Control and Treatment observations are present, and each site–treatment subset has enough observations to fit a linear model.
What does the following code fit?
ggplot(df, aes(x, y, color = treatment)) +
geom_smooth(method = "lm", se = FALSE) +
facet_wrap(vars(site))
ggplot2 fits smoothing lines, it fits one model per unique aesthetic-group combination within each panel. The key is recognizing that two grouping mechanisms are active simultaneously here: color = treatment splits observations into groups, and facet_wrap(vars(site)) splits them into panels. These two mechanisms compound — they don't override each other.
Within each of the three site panels, geom_smooth sees two distinct color groups (Control and Treatment) and fits a separate linear model to each. Three sites × two treatments = six models total, making D the correct answer.
A is wrong because geom_smooth does not fit one global model and copy it everywhere. Each panel receives its own data subset, so no line is ever simply "copied" — every line is fit from the observations actually present in that panel.
B is wrong because faceting does not override the color grouping. Faceting partitions the data into panels, but within each panel, the color aesthetic still creates sub-groups. Both grouping layers remain active.
C is wrong for the same structural reason as B, just from the opposite direction. The color aesthetic does not override faceting either. You don't get just two models shared across sites — the faceting ensures each site's data is handled independently, so treatment-level models are re-fit within every panel.
A useful mental rule: in ggplot2, every distinct combination of panel and aesthetic group gets its own geom_smooth fit. When you see facet_* combined with a grouping aesthetic like color or group, always multiply the panel count by the group count to find the number of models being fit.A factor named group has eight displayed levels ordered A through H. No levels are missing from the data.
Using the default horizontal filling direction, where is the H panel placed by facet_wrap(vars(group), ncol = 3)?
ncol = 3 causes panels to fill vertically before wrapping.facet_wrap(), picture your panels filling a grid left-to-right, then top-to-bottom — exactly like reading English text. With eight panels (A–H) and ncol = 3, you get a grid that is 3 columns wide. Dividing 8 by 3 gives you three rows: the first two rows hold three panels each (A–C, then D–F), and the third row holds the remaining two panels (G and H).
That means G lands in row 3, column 1, and H lands in row 3, column 2 — making C the correct answer.
Choice A is wrong because it places H in row 2, column 3. That position actually belongs to F, the sixth panel. Choice B places H in row 3, column 1, but that slot belongs to G, the seventh panel — H comes immediately after G, one column to the right. Choice D describes a vertical filling order, where panels fill downward through a column before moving to the next. That behavior belongs to facet_grid() or facet_wrap() with dir = "v" specified explicitly; the default direction in facet_wrap() is always horizontal (dir = "h").
A reliable strategy here is to sketch the grid on paper: write out your panel labels in order, filling row by row with the given ncol. Count to your target panel and read off its row and column. This simple sketch eliminates all ambiguity and takes only seconds — a worthwhile habit whenever a facet layout question appears.A wrapped plot has three facets. Values in two facets range roughly from 0 to 10, while one observation in the third facet has a value of 100.
If the plot uses facet_wrap(vars(group)) without a scales argument, which outcome should be expected?
facet_wrap() in ggplot2, the key concept to understand is how y-axis scales are handled across panels. By default — meaning when no scales argument is specified — all panels share a fixed, identical scale on both axes. This shared scale is determined by the global range of the data across all facets combined.
Because one observation reaches 100, the shared y-axis must extend to accommodate that value across every panel. This means the two panels where values only reach 10 will display their data compressed near the bottom of a scale that stretches to 100. That's exactly what option A describes, making it the correct answer.
Option B is wrong because it describes the behavior of scales = "free_y", which allows each panel to set its own independent y range. Without that argument, panels don't get individual scales. Option C is a fundamental misconception — ggplot2 never silently drops observations simply because they stand out from others; the scale expands to include all data points. Option D incorrectly suggests a "spreading" behavior where adjacent panels inherit a modified scale, which is not how ggplot2 works — scales are either fully shared (default) or fully independent ("free"), not partially propagated.
A useful study tip: memorize the four scales options for faceting — "fixed" (default), "free", "free_x", and "free_y". On exam questions, if you see no scales argument, immediately think "everything is fixed and globally shared." That single assumption will let you reason through most faceting questions correctly.A plot is faceted with facet_grid(rows = vars(region), labeller = label_both). One value of region is East.
How does label_both affect the strip for that facet?
East, because strip labels always omit variable names.region, because the labeller replaces values with variable names.region (East), wrapping the value in parentheses after the variable name.region: East, including both the variable name and its value. (correct answer)facet_grid() in ggplot2, the labeller argument controls how strip labels are rendered — specifically, what text appears in the colored band identifying each facet panel. The default labeller shows only the variable's value, but label_both is designed to display more context.
label_both formats strip labels by combining the variable name and its value with a colon-and-space separator, producing output like region: East. This is especially useful when you have multiple faceting variables and want the reader to immediately understand what each strip represents without consulting a legend or title.
D is correct because that colon-space format — "variable: value" — is exactly what label_both produces by definition in ggplot2.
A is wrong because it describes the default labeller behavior (label_value), not label_both. Using label_value, you'd see East alone — but the question explicitly specifies label_both. B reverses the logic entirely: label_both never replaces the value with the variable name; it always shows both, and omitting the value would defeat the purpose of the labeller. C is tempting if you're guessing based on the phrase "label both," but the parentheses format region (East) is not the actual output — ggplot2 uses a colon, not parentheses. There's no standard ggplot2 labeller that uses that parenthetical format.
As a study tip, remember the three core labellers as a set: label_value (value only), label_both (name: value), and label_context (name: value, but only when needed for disambiguation). Knowing their output formats precisely will help you eliminate wrong answers quickly on format-specific questions like this one.A data frame contains observations for four existing region–quarter combinations: East–Q1, East–Q2, West–Q2, and West–Q3. Both regions and all three quarters occur somewhere in the data.
Compare these two plots:
p1 + facet_grid(rows = vars(region), cols = vars(quarter))
p1 + facet_wrap(vars(region, quarter))
With the default facet settings, how many panels does each plot contain?
facet_grid() and facet_wrap() handle missing combinations very differently.
facet_grid() builds a full Cartesian grid from your row and column variables. With 2 regions (East, West) and 3 quarters (Q1, Q2, Q3), it produces 2 × 3 = 6 panels — one slot for every region–quarter combination, even if some cells contain no data. Those empty cells still appear as blank panels. facet_wrap(), by contrast, only creates panels for observed combinations in your data. Since the data contains exactly four region–quarter pairs (East–Q1, East–Q2, West–Q2, West–Q3), facet_wrap() produces 4 panels — no empty slots, no wasted space. This makes B the correct answer: the grid contains six panels, and the wrapped layout contains four.
Choice A has the counts swapped — it mistakenly assigns the smaller number to the grid and the larger to the wrap, which is backwards. Choice C incorrectly assumes both functions suppress empty combinations; only facet_wrap() does this by default. Choice D incorrectly assumes both functions display all possible combinations; that behavior belongs to facet_grid(), not facet_wrap().
A reliable memory hook: think of facet_grid() as a spreadsheet — it always draws the full table, blank cells included. Think of facet_wrap() as a photo album — it only makes a page if there's something to show. On any faceting question, ask yourself first: which function fills in blanks, and which one skips them?A plot uses regions as facet rows and products as facet columns. Some regions have much larger response values than others.
The plot adds facet_grid(rows = vars(region), cols = vars(product), scales = "free_y"). Which description of the resulting y scales is correct?
facet_grid() in ggplot2, the scales argument controls how y (and x) axes are shared across panels — but the key insight is that "free_y" doesn't mean every panel gets its own scale. Instead, it frees scales along rows, meaning panels in the same row still share a y scale, but different rows can have different y ranges.
This is the logic behind answer C being correct. Because region maps to rows (rows = vars(region)), all panels within a given region row share a common y scale. However, since some regions have much larger response values, different rows are permitted to use different y ranges. This is exactly what scales = "free_y" delivers — row-level freedom, not panel-level freedom.
Answer A describes scales = "free", which grants every individual panel a fully independent scale on both axes. That's a different setting entirely. Answer B has the logic backwards: it describes behavior along columns, which would correspond to freeing the x scale (scales = "free_x") when products are mapped to columns — not the y scale. Answer D is simply false; facet_grid() absolutely supports scale freedom through the scales argument, and "fixed" (not the absence of an option) is what forces a single global scale.
A handy memory trick: in facet_grid, "free_y" frees scales across rows (the y-direction of the grid), so row membership still ties panels together — only the row-to-row comparison becomes flexible. When you see scales = in a facet question, always ask which dimension is being freed and which variable defines that dimension.The main data frame has observations from four sites. An annotation data frame contains one column, limit, and has no site column.
Consider this plot:
ggplot(readings, aes(day, value)) +
geom_point() +
geom_hline(data = limits, aes(yintercept = limit)) +
facet_wrap(vars(site))
Assuming limits has one row, what happens to the horizontal reference line?
site variable.ggplot2 applies faceting, it handles layer-level data differently depending on whether that data contains the faceting variable. The key insight: if a data frame passed to a geom lacks the faceting variable (site here), ggplot2 treats that data as a global annotation and replicates it across every panel automatically.
That's exactly what happens here. limits has one row and no site column. When geom_hline receives this data, ggplot2 cannot map any row to a specific panel, so instead of dropping or failing, it draws the line in all four site panels — which is actually the intended, useful behavior for adding a shared reference line to a faceted plot. So A is correct.
B is wrong because ggplot2 doesn't default to the "first level" when the faceting variable is absent — it replicates to all panels, not just one. C is wrong because faceting doesn't produce a single combined backdrop layer; all geoms render inside their respective panels (or all panels if unkeyed). There's no "behind the panels" space where a line would appear. D is the most tempting distractor — you might assume ggplot2 would throw an error for the missing variable — but ggplot2 is explicitly designed to handle this gracefully: a missing faceting key means "show everywhere," not "fail."
A useful rule of thumb: if a data frame lacks the faceting variable, its geom appears in every panel. You can exploit this deliberately when you want a consistent reference line, mean, or annotation across all facets without duplicating rows.The variable tier is a factor with levels Bronze, Silver, and Gold. A filtering operation removes every Gold observation but does not drop the factor's unused Gold level.
What is the result of adding facet_wrap(vars(tier), drop = FALSE) after the filtering operation?
drop = FALSE combines all factor levels together.facet_wrap() in ggplot2, the key distinction to understand is how the function handles factor levels that have no data after filtering. By default, facet_wrap() uses drop = TRUE, which silently removes any panels corresponding to empty factor levels. Setting drop = FALSE overrides this behavior, explicitly telling ggplot2 to retain and display a panel for every level in the factor — even levels with zero remaining observations.
In this scenario, filtering removes all Gold rows but leaves the Gold level intact in the factor structure. When you pass drop = FALSE to facet_wrap(vars(tier)), ggplot2 honors all three factor levels — Bronze, Silver, and Gold — and creates three panels. The Gold panel simply renders empty, with no plotted data inside it. This is answer B, and it's the correct outcome.
Answer A describes the default drop = TRUE behavior, not what happens when you explicitly set drop = FALSE. The whole point of the argument is to prevent the automatic discarding of empty levels. Answer C reflects a fundamental misunderstanding — drop = FALSE does not merge or collapse factor levels; it preserves them as separate panels. Answer D is also wrong because ggplot2 handles unused levels gracefully; an empty panel is a valid, intentional output, not an error condition.
A useful rule of thumb: think of drop = FALSE as a "show your work" instruction to ggplot2 — it forces the plot to acknowledge every level in the factor, even those with nothing to display. This pattern appears not just in faceting but also in grouped summaries and bar charts.A numeric variable named score takes exactly four distinct values—1, 2, 3, and 4—with many observations at each value.
What layout results from facet_wrap(vars(score), ncol = 2)?
facet_wrap() in ggplot2, the key insight is that faceting splits your plot into panels based on the unique values of the faceting variable — not based on whether that variable is numeric or categorical. What matters is how many distinct values exist.
Here, score has exactly four distinct values (1, 2, 3, 4), so facet_wrap(vars(score), ncol = 2) creates four panels, one per unique value, arranged with 2 columns. Since there are 4 panels and 2 columns, ggplot2 automatically fills in 2 rows — giving you a clean 2×2 grid. That makes B the correct answer.
Choice A is wrong because facet_wrap() does not bin numeric values. Binning is something you'd do manually (e.g., with cut()) or via facet_grid() combined with a binning step — it doesn't happen automatically. Choice C reflects a common misconception: continuous variables can define facets as long as there are a manageable number of distinct values. ggplot2 simply treats each unique value as its own panel label. Choice D would only be true if every single observation had a unique value for score — since this variable has only four distinct values, you get four panels, not one per row.
A useful rule of thumb: facet_wrap() always creates exactly as many panels as there are unique values in the faceting variable. When you see ncol = or nrow =, those just control the layout grid, not the panel count. Keep that distinction in mind for any faceting question.An analyst wants one panel for each site. Within every site panel, Control and Treatment observations should be distinguished by color. All panels should retain the default common axis scales.
Which code most directly creates the requested display?
ggplot(df, aes(x, y, color = site)) + geom_point() + facet_wrap(vars(treatment))ggplot(df, aes(x, y)) + geom_point() + facet_wrap(vars(site, treatment))ggplot(df, aes(x, y, color = treatment)) + geom_point() + facet_wrap(vars(site)) (correct answer)ggplot(df, aes(x, y)) + geom_point() + facet_grid(treatment ~ site)ggplot2 visualization, it helps to map each requirement directly to a specific layer or argument before looking at the code. Here, you need three things: panels by site, color by treatment, and default shared axis scales.
facet_wrap(vars(site)) creates one panel per site, and mapping color = treatment inside aes() distinguishes Control from Treatment observations within each panel using color. That's exactly what C does — it satisfies both requirements cleanly and directly. Since facet_wrap uses free scales only when you explicitly set scales = "free", the default behavior already gives you common axes, so no extra argument is needed.
A has the mapping backwards: color = site colors by site instead of treatment, and facet_wrap(vars(treatment)) creates panels by treatment instead of site — the exact opposite of what's requested.
B passes both site and treatment into facet_wrap, which creates a separate panel for every unique site-treatment combination. This over-facets the plot and eliminates the within-panel color distinction entirely, since aes() has no color mapping.
D uses facet_grid(treatment ~ site), which creates a grid with treatment as rows and site as columns — again over-faceting and separating what should be colored within a single panel. It also lacks a color aesthetic.
A useful habit: read the requirements as a checklist — what gets faceted, what gets colored, what stays shared — and verify each aes() mapping and facet_* argument against that list before choosing your answer.