This material has been reproduced and communicated to you by or on behalf of Kaplan Business School pursuant to Part VB of the Copyright Act 1968 (the Act).
The material in this communication may be subject to copyright under the Act. Any further reproduction or communication of this material by you may be the subject of copyright protection under the Act.
Do not remove this notice.
facet_wrap() and facet_grid(), and
decide between shared and free scales.ylim() silently deletes rows, and any statistic drawn on top of
it is then computed from what survived.library(ggplot2) # already installed from Week 10 # today's datasets, all built in faithful # 272 Old Faithful eruptions mpg # 234 cars, from ggplot2 mtcars # 32 cars iris # 150 flowers str(faithful) #> 'data.frame': 272 obs. of 2 variables: #> $ eruptions: num 3.6 1.8 3.33 2.28 4.53 ... #> $ waiting : num 79 54 74 62 85 ...
geom_hex() needs install.packages("hexbin"). Everything else today
runs in a fresh session with ggplot2 alone.Old Faithful is a geyser in Wyoming. The dataset records how long each eruption lasted and how long the wait was before it.
| Statistic | eruptions (minutes) |
|---|---|
| n | 272 |
| minimum | 1.600 |
| first quartile | 2.163 |
| median | 4.000 |
| third quartile | 4.454 |
| maximum | 5.100 |
| mean | 3.488 |
Those seven numbers describe this variable badly, and the next slide shows why.
# counts in bins ggplot(faithful, aes(eruptions)) + geom_histogram(binwidth = 0.25) # a smoothed estimate of the same thing ggplot(faithful, aes(eruptions)) + geom_density(fill = "steelblue", alpha = 0.3) # five numbers ggplot(faithful, aes(y = eruptions)) + geom_boxplot() # shape and summary together ggplot(faithful, aes(x = "", y = eruptions)) + geom_violin(fill = "grey90") + geom_boxplot(width = 0.1) # or show the data itself alongside ggplot(faithful, aes(x = "", y = eruptions)) + geom_violin(fill = "grey90") + geom_jitter(width = 0.08, alpha = 0.4) summary(faithful$eruptions) #> Min. 1st Qu. Median Mean 3rd Qu. Max. #> 1.600 2.163 4.000 3.488 4.454 5.100
# the summary ggplot(faithful, aes(y = eruptions)) + geom_boxplot() # the data behind it ggplot(faithful, aes(x = "", y = eruptions)) + geom_jitter(width = 0.15, alpha = 0.45) # both together, which is what you should draw ggplot(faithful, aes(x = "", y = eruptions)) + geom_violin(fill = "grey92") + geom_jitter(width = 0.08, alpha = 0.4) + labs(x = NULL, y = "Eruption length (minutes)") # the numbers behind the claim sum(faithful$eruptions > 3 & faithful$eruptions < 3.5) #> 7 sum(faithful$eruptions < 3) #> 97 sum(faithful$eruptions >= 3) #> 175 median(faithful$eruptions) #> 4
# the default, with the message it prints ggplot(faithful, aes(eruptions)) + geom_histogram() #> `stat_bin()` using `bins = 30`. Pick better value #> with `binwidth`. # say what you mean, in minutes ggplot(faithful, aes(eruptions)) + geom_histogram(binwidth = 0.25) # or in bins, if the count is what matters ggplot(faithful, aes(eruptions)) + geom_histogram(bins = 12) # two groups on one axis ggplot(mpg, aes(hwy, fill = drv)) + geom_histogram(binwidth = 2, position = "identity", alpha = 0.5) # position = "identity" overlaps them. # The default, "stack", makes the upper groups # unreadable because they no longer start at zero.
| Geom | Shows | Hides | Reach for it when |
|---|---|---|---|
| geom_histogram() | the shape, as counts you can add up | anything narrower than the bin width | one variable, and the reader cares about how many |
| geom_density() | the shape, smoothed | the sample size, and the gaps between observations | comparing the shape of two or three groups |
| geom_boxplot() | median, quartiles, outliers | the shape entirely, including extra modes | many groups side by side, where shape is secondary |
| geom_violin() | the shape, mirrored, per group | the individual observations | a handful of groups where shape matters |
| + geom_jitter() | every observation | nothing, which is the point | n is under about 500, so add it to any of the above |
faithful$eruptions shows a median of 4.00 and a box from 2.16 to 4.45. What does that tell you about the shape?geom_histogram() prints a message about bins = 30. What is it telling you?# the problem, measured before you draw nrow(mpg) #> 234 nrow(unique(mpg[, c("displ", "hwy")])) #> 126 # rectangular bins, width in data units ggplot(mpg, aes(displ, hwy)) + geom_bin2d(binwidth = c(0.5, 2)) # hexagonal bins, which tile more evenly # needs install.packages("hexbin") ggplot(mpg, aes(displ, hwy)) + geom_hex(bins = 20) # what ggplot computed p <- ggplot(mpg, aes(displ, hwy)) + geom_bin2d(binwidth = c(0.5, 2)) d <- ggplot_build(p)$data[[1]] nrow(d) #> 53 bins drawn max(d$count) #> 17 busiest bin sum(d$count) #> 234 every car accounted for # the escalation, in order # 1. alpha up to a few thousand points # 2. geom_bin2d tens of thousands # 3. geom_hex same, better tiling
geom_text() or a distinct fill so the reader knows.# Week 9 produced the table tab <- as.data.frame(table(mpg$class, mpg$drv)) names(tab) <- c("class", "drv", "n") nrow(tab) #> 21 every combination sum(tab$n == 0) #> 9 including the empty ones # Week 11 draws it ggplot(tab, aes(x = drv, y = class, fill = n)) + geom_tile(colour = "white") + geom_text(aes(label = n), colour = "white", size = 3) + scale_fill_gradient(low = "#132B43", high = "#56B1F7") + labs(x = "Drive type", y = NULL, fill = "Cars") # geom_tile needs one row per cell. # aggregate() and table() differ here: # table() returns every combination, zeros included # aggregate() returns only the combinations present # If you aggregate first, the empty cells vanish # from the chart without any warning.
Three examples in circulation for this topic carry titles that describe a different chart from the one the code draws. They are worth a minute because the same mistake is the easiest way to lose marks in Assessment 3.
| The label says | The code actually does | Why it matters |
|---|---|---|
| "Car horsepower and torque" | aes(x = hp, y = wt), and wt is weight in thousands of
pounds |
A reader who knows cars will assume you do not. |
| "Temperature variations by month" | ggplot(mtcars, aes(factor(cyl), mpg)). mtcars has no temperature and no
month. |
The axis labels contradict the title on the same slide. |
| "Stacked bar plots" | geom_boxplot() |
Naming the geom wrongly suggests you do not know which one you used. |
aes() call, then read your axis labels. All three have
to name the same variables. It takes ten seconds per chart and it is worth marks under two separate
criteria.Each one is a one-line correction. The point is the habit, not the syntax.
# say what the axes actually are ggplot(mtcars, aes(x = hp, y = wt)) + geom_bin2d(binwidth = c(50, 0.5)) + labs(title = "Heavier cars carry bigger engines", x = "Horsepower", y = "Weight (1000 lbs)") # a title that names the variables in the aes() ggplot(mtcars, aes(factor(cyl), mpg)) + geom_boxplot() + labs(title = "Fuel economy falls as cylinders rise", x = "Cylinders", y = "Miles per gallon") # and if you want a genuinely stacked bar ggplot(mpg, aes(class, fill = drv)) + geom_bar(position = "stack") + labs(title = "Drive type by vehicle class", x = NULL, y = "Cars", fill = "Drive")
aggregate() and three cells are missing from the chart entirely. Why?aes(x = hp, y = wt). Under the Assessment 3 rubric, which criteria does that damage?# one panel per level of one variable ggplot(mpg, aes(displ, hwy)) + geom_point() + facet_wrap(~ class) # control the layout facet_wrap(~ class, ncol = 4) facet_wrap(~ class, nrow = 2) # the tilde means "by". It is a formula, so the # variable name is not quoted. # how many panels, and how many points in each table(mpg$class) #> 2seater compact midsize minivan #> 5 47 41 11 #> pickup subcompact suv #> 33 35 62 # facet on two variables with wrap, and you get # one panel per observed combination facet_wrap(~ class + drv) # Shared scales are the default and they are # what makes panels comparable. Changing that # is the next slide.
# the default: every panel on the same axes facet_wrap(~ class) # each panel fitted to its own data facet_wrap(~ class, scales = "free") # free on one axis only facet_wrap(~ class, scales = "free_y") facet_wrap(~ class, scales = "free_x") # the ranges that produce the difference aggregate(hwy ~ class, mpg, range) #> class hwy.1 hwy.2 #> 2seater 23 26 #> compact 23 44 #> pickup 12 22 # A reader assumes panels are comparable unless # told otherwise, because that is the default. # Using free scales without saying so is the # faceting equivalent of truncating an axis.
# rows ~ columns ggplot(mpg, aes(displ, hwy)) + geom_point() + facet_grid(drv ~ cyl) # one row, several columns facet_grid(. ~ drv) # several rows, one column facet_grid(drv ~ .) # the combinations that exist table(mpg$drv, mpg$cyl) #> 4 5 6 8 #> 4 23 0 32 48 #> f 58 4 43 1 #> r 0 0 4 21 # facet_grid keeps every combination, so gaps show # facet_wrap keeps only what occurs, so gaps vanish # # Use grid when the absence of a combination is # part of what you are reporting. Use wrap when # you only have one variable, or when the empty # cells would waste the page.
Week 7's reversal, Week 9's grouped means and Week 10's three fitted lines were all versions of this question. Faceting answers it directly.
Above about six categories, colours stop being distinguishable. Panels have no such limit.
Three overlapping clouds in one panel hide each other. Three panels separate them without changing a single value.
Two or three groups compared directly are easier to read in one panel with colour. Panels force the eye to travel.
A panel with 5 points invites a conclusion it cannot support. Report the counts, or combine the small groups.
If the panels only look reasonable on free scales, the faceting variable is probably doing something other than what you think.
facet_wrap(~ class) gives seven panels and every one has the same axes. Did you ask for that?facet_grid(drv ~ cyl) produces twelve panels and three are empty. What should you do?# What does not work, and why ggplot(iris_summary, aes(x = Species)) + geom_bar(aes(y = Avg_Petal_Length), stat = "identity", position = "dodge") + geom_bar(aes(y = Avg_Petal_Width), stat = "identity", position = "dodge") # position = "dodge" separates groups WITHIN one # layer. It cannot separate two layers, so the # second simply draws on top of the first. # Step 1: aggregate (Week 9) ag <- aggregate(cbind(Petal.Length, Petal.Width) ~ Species, data = iris, FUN = mean) # Step 2: reshape to one row per bar lg <- reshape(ag, direction = "long", varying = c("Petal.Length", "Petal.Width"), v.names = "value", timevar = "measure", times = c("Petal.Length", "Petal.Width"), idvar = "Species") nrow(ag) #> 3 nrow(lg) #> 6 one row per bar # Step 3: one layer, fill does the clustering ggplot(lg, aes(Species, value, fill = measure)) + geom_col(position = "dodge", width = 0.7) + labs(y = "Mean measurement (cm)", fill = NULL)
# the chart to avoid ggplot(data.frame(x = c("Mean", "Median"), y = c(mean(mtcars$mpg), median(mtcars$mpg))), aes(x, y)) + geom_col(fill = "steelblue") # the chart to draw instead ggplot(mtcars, aes(mpg)) + geom_histogram(binwidth = 2, fill = "grey40") + geom_vline(xintercept = mean(mtcars$mpg), colour = "red", linetype = "dashed") + geom_vline(xintercept = median(mtcars$mpg), colour = "blue", linetype = "dashed") + labs(x = "Miles per gallon", y = "Cars") mean(mtcars$mpg) #> 20.091 median(mtcars$mpg) #> 19.2 sd(mtcars$mpg) #> 6.027 # when you do want summary bars, show the # uncertainty on them ggplot(mtcars, aes(factor(cyl), mpg)) + stat_summary(fun = mean, geom = "col", fill = "grey60") + stat_summary(fun.data = mean_se, geom = "errorbar", width = 0.2)
# DELETES rows, then fits ggplot(mpg, aes(displ, hwy)) + geom_point() + geom_smooth(method = "loess", formula = y ~ x) + ylim(20, 40) #> Warning: Removed 81 rows containing non-finite #> values (`stat_smooth()`). # KEEPS rows, then zooms ggplot(mpg, aes(displ, hwy)) + geom_point() + geom_smooth(method = "loess", formula = y ~ x) + coord_cartesian(ylim = c(20, 40)) # these two are the same thing: ylim(20, 40) scale_y_continuous(limits = c(20, 40)) # proof a <- ggplot(mpg, aes(displ, hwy)) + geom_point() + geom_smooth(method = "loess", formula = y ~ x) b1 <- ggplot_build(a + ylim(20, 40)) b2 <- ggplot_build(a + coord_cartesian(ylim = c(20, 40))) sum(!is.na(b1$data[[1]]$y)) #> 153 sum(!is.na(b2$data[[1]]$y)) #> 234 # Rule: to change what is COMPUTED, use a scale # limit. To change what is SEEN, use # coord_cartesian. Cropping a view is # almost always what you meant.
two <- subset(mpg, class == "2seater")
ggplot(mpg, aes(displ, hwy)) +
geom_point(colour = "grey70") +
geom_point(data = two, colour = "#CC0000",
size = 2.5) +
annotate("text", x = 4.3, y = 34,
label = "Five Corvettes",
colour = "#CC0000") +
annotate("segment", x = 4.7, xend = 5.9,
y = 33, yend = 26, colour = "#CC0000",
arrow = arrow(length = unit(2, "mm"))) +
labs(title = "Bigger engines use more fuel, with one exception",
subtitle = "234 cars, model years 1999 and 2008",
x = "Engine displacement (litres)",
y = "Highway economy (mpg)",
caption = "Source: US EPA fuel economy data") +
theme_minimal()
# the pattern: grey everything, then redraw the
# subset you care about on top of it.
# reference lines
geom_hline(yintercept = mean(mpg$hwy), linetype = "dotted")
geom_vline(xintercept = 4)
geom_abline(slope = -3.53, intercept = 35.7)
nrow(two) #> 5
mean(two$displ) #> 6.16
mean(two$hwy) #> 24.8p <- ggplot(mpg, aes(displ, hwy, colour = drv)) +
geom_point()
p +
scale_colour_manual(
values = c("4" = "#1B4965",
"f" = "#5FA8D3",
"r" = "#CAE9FF"),
labels = c("Four wheel", "Front wheel",
"Rear wheel")) +
labs(title = "Heavier cars pay for it at the pump",
subtitle = "234 US models, 1999 and 2008",
x = "Engine displacement (litres)",
y = "Highway economy (mpg)",
colour = "Drive",
caption = "Source: US EPA") +
theme_minimal(base_size = 13) +
theme(legend.position = "bottom",
plot.title = element_text(face = "bold"))
# export at the size it will be shown
ggsave("engine-economy.png",
width = 10, height = 5.6, dpi = 300)
# 10 by 5.6 inches is 16:9, which fills a slide.
# Text in ggplot is sized in points and does not
# scale, so saving small and enlarging in
# PowerPoint gives you coarse, oversized text.geom_bar() layers with different aes(y = ) and position = "dodge" draw one visible bar per group. Why?ylim(20, 40) to a plot with a smooth and the curve changes shape. What happened?| Item | Detail |
|---|---|
| Title | Business Decision Case Study |
| Type | Individual presentation and report |
| Weighting | 40 per cent, split 20 presentation and 20 report |
| Total marks | 40 |
| Report length | 800 words, plus or minus 10 per cent |
| Presentation length | As advised by your facilitator, based on class size |
| Presentation | Week 12, in class |
| Submission | Week 13, Tuesday 23:59 AEST, via MyKBS |
| Outcomes | LO3, evaluate and apply visualisation techniques. LO4, design visualisations to support decision-making. |
Take a real business decision, find data that bears on it, visualise that data in ggplot2, and recommend what to do.
| Criterion | Pass looks like | Distinction looks like |
|---|---|---|
| Case study and business relevance 8 marks |
Broadly relevant, but general and only partly connected to a decision | Specific, grounded in a credible context, with a clear decision focus |
| Visualisation design and execution 8 marks |
Basic and partly effective, with issues in formatting, labelling or readability | Well designed and accurate, with effective labels, scales, themes and annotations |
| Analysis and recommendations 8 marks |
Identifies some patterns; interpretation limited and recommendations thin | Thoughtful and well supported, with practical and justified recommendations |
| Presentation and communication 6 marks |
Main points get across, but clarity, structure or pacing suffer; slides basic | Well organised, engaging, professionally delivered, slides support the message |
| Code and report quality 10 marks |
Provided, but documentation, structure or referencing is basic or inconsistent | Well documented and easy to follow; report clear, concise, structured, referenced |
A genuine business decision, supported by data that can be analysed visually. Use your own workplace, a previous employer, or an industry you know.
Import it into R. Clean, prepare and transform as needed. Annual reports, government datasets, industry reports and credible websites are all acceptable.
ggplot2. Choose plot types, scales, labels, themes and annotations so the charts are accurate, readable and suited to the audience.
Identify patterns, trends, comparisons and relationships. Explain the business problem and develop practical recommendations that follow from what you drew.
Present in class in Week 12. Submit the report in Word, your slides, your R code as a .R file, and the data files, by Week 13 Tuesday 23:59.
| By | You should have |
|---|---|
| End of today | A decision written as one sentence, and a candidate dataset you have actually opened |
| This weekend | The data loading into R without manual edits, and one chart that says something |
| Two days before class | All charts built and exported. Slides drafted. Rehearsed once against a clock |
| Week 12 | Present |
| Week 13, Tuesday 23:59 | Report in Word, slides, code as .R, data files, all uploaded to MyKBS |
Write it as a sentence with three parts: who has to decide, what the options are, and by when.
| Works | Why |
|---|---|
| "Should the cafe drop its Sunday trading hours next quarter?" | Two options, a deadline, and sales data by day and hour would settle it |
| "Which two of our six product lines should get next year's marketing budget?" | A ranking question with a fixed budget, answerable from revenue and margin |
| "Should the council put the new bus route through the north or the east corridor?" | Two named alternatives, with public transport and census data available |
| "Is our December staffing level too high for the volume we actually get?" | A number to compare against a pattern, with an obvious action either way |
| Struggles | Why |
|---|---|
| "An analysis of the Australian housing market" | No decision, no decider, no options. This is a topic |
| "Exploring the mpg dataset" | No business context at all, and we have used it for four weeks |
| "How can our company improve customer satisfaction?" | A decision in principle, but the options are unbounded so no chart can close it |
| "Predicting next year's sales" | A forecasting task, not a decision, and it needs methods this subject has not taught |
You have eleven weeks of techniques. These are the ones that answer business questions, with the week they came from.
| If your question is | Draw | From | Watch for |
|---|---|---|---|
| Has it changed over time? | Line chart, geom_line() | Week 6 | A truncated y axis, and a start date chosen to flatter the trend |
| Which category is largest? | Bar chart, geom_col(), sorted | Weeks 1, 10 | Alphabetical ordering, and bars that do not start at zero |
| Do these two move together? | Scatter with geom_smooth() | Weeks 4, 10 | Overplotting, and a pooled trend that reverses within groups |
| How is it spread? | Histogram or violin with jitter | Weeks 3, 11 | A boxplot hiding two groups, and an inherited bin width |
| Does it hold in every segment? | facet_wrap(), shared scales | Weeks 7, 11 | Panels with too few observations to support a claim |
| How do two categories cross? | geom_tile() on an aggregate | Weeks 9, 11 | Combinations that never appear, silently dropped |
| Is the comparison fair? | Per-unit rates, not totals | Week 9 | The largest total and the best rate are often different groups |
| Slide | Contains | Says |
|---|---|---|
| 1 | Title, your name, the decision | "Ravenswood Cafe has to decide whether to keep trading on Sundays." |
| 2 | The data: source, period, rows, what you cleaned | "Point of sale exports, 14 months, 31,402 transactions, 212 voided rows removed." |
| 3 to 6 | One chart each, one finding each | "Sunday revenue is 38 per cent of Saturday and falls all year." |
| 7 | The recommendation, tied to the charts | "Close Sundays from June. Slides 4 and 5 are the reason." |
| 8 | What the data cannot settle | "This cannot tell us whether Sunday customers return midweek." |
| Section | Words | Job |
|---|---|---|
| The decision | 100 | Who decides, between what, by when, and why it matters |
| The data | 120 | Source, period, size, and exactly what you cleaned or transformed |
| The visualisations | 320 | One short paragraph per chart: what it shows, and what you read from it |
| Recommendations | 180 | What to do, tied to a named figure, with the expected effect |
| Limitations | 80 | What the data cannot settle, and what you would collect next |
| Total | 800 | Plus or minus 10 per cent, so 720 to 880 |
Penalties may be applied for submissions that exceed the prescribed limit.
Ten marks cover code and report together. The code half is the easiest place in this subject to pick up marks: it is entirely under your control and needs no new analysis.
# TECH3100 Assessment 3 | Student name, number # Ravenswood Cafe: should Sunday trading continue? # Last run: R 4.3.3 on 2026-10-14 # 1. PACKAGES ------------------------------------------ library(ggplot2) # 2. IMPORT -------------------------------------------- # Relative path, so the folder runs anywhere sales <- read.csv("data/pos_export_2025.csv") nrow(sales) # 31402 transactions before cleaning # 3. CLEAN --------------------------------------------- # Voided sales carry a negative total and must not be # counted as revenue (212 rows). sales <- subset(sales, total > 0) sales$weekday <- weekdays(as.Date(sales$date)) # 4. AGGREGATE (Week 9) -------------------------------- by_day <- aggregate(total ~ weekday, sales, sum) # 5. FIGURE 1: revenue by weekday ---------------------- # Sorted by value: alphabetical order hides the # ranking the decision turns on. ggplot(by_day, aes(reorder(weekday, total), total)) + geom_col() + coord_flip() + labs(title = "Sunday takes less than half of Saturday", x = NULL, y = "Revenue ($)") ggsave("figures/fig1-weekday.png", width = 10, height = 5.6, dpi = 300)
# subset the data tells a marker nothing. # Voided sales carry a negative
total tells them you understood your data.| File | Check | |
|---|---|---|
| 1 | Report, .docx | 720 to 880 words. Figures numbered and referred to by number. References consistent. |
| 2 | Slides | The deck you actually presented, with the charts at readable size. |
| 3 | Code, .R | Header block, numbered sections, comments explaining why. Not a notebook, not pasted into Word. |
| 4 | Data files | In a format your code reads directly. Relative paths, not
C:/Users/... |
| 5 | GenAI appendix, if used | All prompts and responses, plus a reference in the KBS format. |
ggsave().Use of generative AI is optional for this assessment. You may use it for research and content generation, provided it is appropriately referenced. You do not have to use it.
| Permitted | Required if you do |
|---|---|
| Expanding your understanding of a technique | A reference, in the same style as any other source |
| Idea generation in the research phase | An appendix documenting the collaboration |
| Producing content that enhances the assessment, such as images | Every prompt and every response used, in that appendix |
Referencing guidance is on the Kaplan Library site, under referencing other sources.
| Criterion | What drops you into the lower bands | The fix, which is usually small |
|---|---|---|
| Case study 8 marks |
A topic rather than a decision. Nobody in the story has to choose anything. | Name the decider and the two options in your first sentence. |
| Visualisation 8 marks |
Default axis labels reading displ and hwy. Unsorted bars.
A truncated axis. A title that names a variable not on the chart. |
labs() on every figure, reorder() on every bar chart, and read
the title against the aes(). |
| Analysis 8 marks |
Describing the chart instead of reading it. "Revenue was highest in December" is a description; it is not yet a finding. | For each chart write the sentence that starts "so we should". |
| Presentation 6 marks |
Reading the slides. Overrunning. Charts too small to read from the back of the room. | Rehearse once against a clock. Export at 10 by 5.6 inches and 300 dpi. |
| Code and report 10 marks |
Uncommented code. Absolute file paths. A report over the word limit. Figures with no numbers and no references in the text. | Header block, numbered sections, relative paths, and one full run in a clean session. |
Every technique this subject has taught makes a choice on your behalf if you do not make it yourself.
| Week 8 | Mean imputation chose to shrink your variance |
| Week 9 | An inner join chose which records to discard |
| Week 10 | Mapping a constant inside aes() chose a colour
that was not the one you named |
| Week 11 | 30 bins, shared scales, and a scale limit that deletes rows |
"Who has to decide what, by when." If you cannot write it, you do not have a case study yet, and that is the first eight marks.
Not into Excel. Into R, with read.csv() and a relative path, running from a
script you can hand in.
One. With a title stating the finding and both axes labelled. If you can build one you can build four.
Out loud, standing, with the slides on screen. Confirm your length with me first. Most overruns happen on the data slide.
New session, new folder, top to bottom, no manual steps. Do it now rather than at 23:00 on the Tuesday of Week 13.
About your data, your decision, or which chart to use. Bring the actual file. Ten minutes with it open beats an hour describing it.
Press T or Escape to close. Arrow keys to navigate.