Interview guides · Columbia University
Columbia University Data Scientist Interview Questions & Guide 2026
Data scientist prep for Columbia University candidates: drill A/B design, power and minimum detectable effect on original exercises.
The 60-second brief
The role of a Data Scientist at Columbia University is critical in driving innovative research and data-driven decision-making across various departments. As a Data Scientist, you will be responsible for analyzing complex datasets, developing predictive models, and translating data insights into actionable strategies that enhance research outcomes and operational efficiency. Your work will directly impact academic research, contribute to groundbreaking discoveries, and improve the experience of students, faculty, and the broader community.
Coding rounds for this role are usually data-manipulation shaped rather than data-structure shaped: group-bys, joins, time windows, ranking within a partition. Confirm the format before spending a week on graph traversal.
Focus areas
- Cluster experiments at class or school level
- Model seat activation as the renewal leading indicator
- Align cohorts to term weeks, not calendar weeks
Overview
This position is unique in its combination of academic rigor and practical application. You will collaborate with interdisciplinary teams, engage with cutting-edge technologies, and address complex questions in fields such as healthcare, social sciences, and engineering. The role not only requires technical expertise but also a strong ability to communicate findings to non-technical stakeholders, making it a highly impactful and fulfilling career path.
The Columbia University interview process
Columbia University candidates report 3 rounds · ≈ 3-5 weeks. The stages below are what candidates describe, not a published process.
Phone Screening
Whoever runs this call is usually not a practitioner. They take notes, and a hiring manager skims those notes later, so the real question is whether your work survives being written down by someone outside the field. Test every project sentence against that: could a non-specialist repeat it correctly without knowing what a propensity score is? Carry a plain-language version of each project and one reason you want this particular role that you could not copy onto another application. Vagueness at this stage reads as inexperience, even when the underlying work was genuinely deep.
What to demonstrate
- Whether a non-specialist can restate your projects accurately, since their paraphrase is what reaches the hiring manager
- Whether your reason for wanting the role points at the work itself rather than the company's reputation
- Whether your language signals the level being screened for: what you decided yourself versus what you were handed
How to prepare
- Write a two-sentence, jargon-free version of each major project: the question nobody could answer, and the decision your work changed. Read it to someone outside data and have them repeat it back
- Point your 'why this role' answer at something concrete in the job description or the product surface you would be working on, and keep it to two sentences
- Have two questions ready about measurement: which metric the team is held to, and who acts on an analysis once it lands
Video Interviews
An added round often puts you in front of someone outside the core hiring team: a partner engineer, a product owner, a domain expert, sometimes a more senior manager. The question they are really asking is not whether you can do the work but whether they would trust a number that came from you. That changes what a good answer looks like. Lead with what the decision cost and what it changed, keep the method available but not central, and be plain about the limits of your evidence. Overstating a result is the fastest way to lose this round.
What to demonstrate
- Whether you can explain a technical choice to someone who will never read your code, without either flattening it into nothing or hiding inside jargon
- Honesty about evidence strength: what the analysis establishes, what it only suggests, and what it cannot say at all
- How you take disagreement, specifically whether you update on a good objection, hold your position with reasons, or fold on contact
How to prepare
- Write the two-sentence version of your most technical project for a non-specialist, then check that neither sentence needs a method name to make sense.
- For one result you are proud of, write the strongest objection someone could raise and a response that concedes the part of it that is correct.
- Prepare one decision that turned out to be wrong: how you found out, what it cost, and what you changed afterwards. A senior cross-functional interviewer asks for this more often than a technical one does.
Technical Assessment
Before anything else, this round is a reading test. You are given a small schema and a question phrased in business language, and most of the difficulty sits in the gap between them. Who counts as an active user, does a refunded order still count as an order, is that date column an event time or a load time. Weak answers start typing immediately and compute something precise about the wrong population. Strong ones pin the definition in one sentence, name the column that encodes it, then write the query. On a timed assessment with nobody to tell, write the definition in a comment anyway.
What to demonstrate
- Whether an ambiguous term becomes a specific column and filter before any computation happens
- Whether you read the schema for keys and cardinality rather than only for column names
- Whether the result answers the question at the grain it was asked at, per user or per session or per day
How to prepare
- Take three metrics you already use and write down the exact filter and exact grain behind each, then practise stating one of them in a single sentence out loud
- On a schema you have never seen, spend the first minute writing what one row of each table means and which key it is unique on, then predict which joins can duplicate rows
- Rehearse a version where the definition changes halfway through, and edit the query you have instead of starting over
Where candidates lose points
Adaptive item selection holds observed accuracy flat by construction.
A selector targeting a fixed success probability, say 70%, will keep measured first-attempt accuracy near 70% whether learners are improving or not, because as theta rises the engine simply serves harder items. Reporting 'accuracy improved 3 points' on adaptive content therefore usually means the selector got more conservative, not that anyone learned more. Accuracy is only interpretable on a fixed form with unchanged item versions, which is why the first-attempt accuracy metric above carries both restrictions.
Learner-level standard errors on class-level interventions.
Anything an instructor controls, and anything deployed by school, is assigned at the section or school level, and outcomes within a section are correlated through the shared instructor, schedule, and device fleet. Treating the learner as the unit of independence understates variance by the design effect 1 + (m - 1) * rho for roughly equal cluster sizes. At a typical section size of 25 and rho of 0.15 that is a factor near 4.6 on variance, which routinely converts a null into a 'significant' result.
Reporting a mean for a heavy-tailed metric without saying what it hides
For spend, session length or items per order, a small fraction of units carries most of the total, so the mean has a wide standard error and one account can move it. Fix the handling before you see the result: cap or winsorise at a pre-declared percentile, and report the median or the share above a threshold next to the mean. Capping changes the estimand, so say which question the capped number answers, and check how much of any difference comes from the top 0.1 percent of units.
Interpreting a change before checking data quality and logging
Spend the first pass on row volume by day, null rates, duplicate keys, and whether the step change lands on a release or tracking-migration date. A discontinuity that coincides with a deploy is an instrumentation hypothesis before it is a behavioural one.
Questions & practice
Discuss the time complexity of various sorting algorithms.
Medium · machine learning and modelling
Approach
- Say how the offline result would be validated online before it is trusted.
- Check what information would not exist at prediction time, and exclude it.
- Set a baseline first, so any model has something honest to beat.
Follow-up
- How would you choose the decision threshold, and who owns that choice?
- Where could label leakage enter this setup?
Simulate the gain a bottom-quartile selection manufactures
Medium · regression to the mean · simulation · measurement error · selection bias
Observed quiz scores are a true score plus independent noise, both normal, with reliability r equal to true-score variance over observed-score variance. Simulate 200,000 learners, standardise the pretest to mean 0 and SD 1, select the bottom quartile on the pretest, and measure the mean pretest-to-posttest change with no intervention at all. Report the manufactured gain for r in {0.5, 0.7, 0.9, 1.0}, and give the closed form your simulation should reproduce. Use numpy only, no statistical packages.
Approach
- Parameterise by r directly: draw the true score with variance r and each noise term with variance 1 - r, so the observed score has unit variance and reliability exactly r by construction. Draw one true score and two independent noise terms per learner.
- Select on the pretest and only the pretest. Selecting on the true score, or on the average of the two measurements, removes the correlation between selection and the pretest's own noise, and the artefact disappears. That sensitivity is the lesson.
- Compute the mean of posttest minus pretest over the selected group. The true score cancels in the difference, so whatever remains is entirely the difference of two noise draws conditioned on the first being low.
- Check against the closed form. For jointly normal standardised scores, E[posttest | pretest] = r * pretest, so the expected gain is (1 - r) * |E[pretest | bottom quartile]|, and E[pretest | bottom quartile] = -phi(z_0.25) / 0.25 = -1.2711.
- Extend the script with a control group selected by the identical rule from an untreated population and show the difference of differences returns to zero. That is the design fix you would actually propose, not a caveat in a footnote.
Worked solution (25 min)
- For each r: t = rng.normal(0, sqrt(r), n); e1, e2 = rng.normal(0, sqrt(1 - r), n) twice; pre = t + e1; post = t + e2.
- sel = pre <= np.quantile(pre, 0.25); gain = (post[sel] - pre[sel]).mean().
- Compare gain to (1 - r) * 1.2711 and print the absolute difference.
- Repeat the whole loop over the four r values and tabulate simulated against closed form.
- Add the untreated control arm selected by the same rule and report the difference of differences.
Expected result: Mean manufactured gain close to (1 - r) * 1.2711 standard deviations: about 0.636 at r = 0.5, 0.381 at r = 0.7, 0.127 at r = 0.9, and 0 at r = 1.0, each within roughly 0.01 at 200,000 draws. The difference of differences against an identically selected control is zero within Monte Carlo error at every r.
Verify it yourself
- r = 1.0 must give a gain indistinguishable from zero; any systematic positive value means noise leaked into the true-score draw.
- Selecting the top quartile instead gives a mirror-image loss of the same magnitude.
- The Monte Carlo standard error on the selected group of about 50,000 is roughly 0.0045 at r = 0.5, so a discrepancy above about 0.015 is a bug, not sampling noise.
Follow-up
- A published case study reports large gains specifically for learners who started in the bottom quartile. What do you ask for before believing any of it?
- The posttest is twice as long as the pretest, so its reliability is higher. Does the manufactured gain grow or shrink, and why?
- Give a design that measures a real effect on exactly this selected population without a randomised control.
Compute pace adherence at term-week six
Easy · metric implementation · calendar alignment · null handling
Given fct_enrollment (enrollment_id, learner_id, course_id, section_id, term_id, enrollment_source, enrolled_at, scheduled_start_date, due_date, completed_at, units_total, units_completed, status) and dim_term (term_id, term_start_date, term_end_date, term_length_weeks), compute the share of enrollments at or ahead of pace at the end of term-week 6. An enrollment is on pace when units_completed >= units_total * (6 / term_length_weeks). Count only enrollments active at that moment. Handle NULL scheduled_start_date and units_total of zero explicitly, and return one value per term with its denominator.
Approach
- Join to dim_term on term_id and derive the cutoff as term_start_date plus 42 days. The metric is anchored to the term calendar, not to each enrollment's own start, which is what makes it comparable across institutions on different calendars.
- Resolve NULL scheduled_start_date by falling back to term_start_date, and count how often the fallback fired. A large fallback share is a finding about roster sync, not a detail to bury.
- Reconstruct active-at-cutoff rather than trusting the status column: enrolled_at <= cutoff and (completed_at is null or completed_at > cutoff). If status is current-state only, say so, because then filtering on it removes learners who fell behind and dropped later.
- Exclude units_total = 0 from both numerator and denominator and report that count separately. Left in, 0 >= 0 marks every empty enrollment as on pace and drags the rate up.
- Group by term_id and return numerator, denominator, and rate together, never the rate alone.
Follow-up
- A two-week holiday falls inside weeks one to six for one term. How do you stop that punishing those enrollments without hand-editing the threshold?
- Two terms have term_length_weeks of 10 and 16. Is a single week-6 number comparable across them, and what would you report instead?
How would you optimize a slow-running SQL query?
Medium · sql and data manipulation
Approach
- Compute rates by summing numerator and denominator separately, never by averaging rates.
- State the window function and its partition and ordering out loud before writing it.
- Say which table is the grain you start from, and join outward from it.
Follow-up
- How would you verify this result without re-running the same query?
- How does the query change if the join becomes one-to-many?
Show how you would visualize data using Python libraries like Matplotlib or Seaborn.
Medium · sql and data manipulation
Approach
- Say which table is the grain you start from, and join outward from it.
- Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.
- Check whether any join is one-to-many before aggregating, or the sums inflate.
Follow-up
- What breaks if events arrive late or out of order?
- How does the query change if the join becomes one-to-many?
Deduplicate retried submissions before computing first-attempt accuracy
Medium · window functions · deduplication · fan-out
A client retry bug wrote duplicates into fct_assessment_response(response_id, learner_id, content_item_id, content_version_no, attempt_no, submitted_at, is_correct, max_points, scoring_mode): the same learner, item, version and attempt_no appears two or three times, submitted_at within two seconds, different response_id. Deduplicate keeping the earliest row per logical attempt, then compute 28-day first-attempt accuracy over items whose course has dim_course.uses_adaptive_selection = FALSE and whose (content_item_id, version_no) did not change inside the window. Report how many rows the dedup removed and its share of raw rows.
Approach
- Rank with ROW_NUMBER() OVER (PARTITION BY learner_id, content_item_id, content_version_no, attempt_no ORDER BY submitted_at, response_id) and keep rn = 1. Including response_id in the ORDER BY makes the survivor deterministic when submitted_at ties, which it will at second resolution.
- Validate the duplicate definition before deleting anything. Count partitions with rn > 1 and inspect MAX(submitted_at) - MIN(submitted_at) inside each. A spread of minutes is a genuine re-attempt the client failed to increment attempt_no for, and dropping it is data loss rather than dedup.
- Apply the version restriction by excluding content_item_id values that show more than one distinct content_version_no among responses in the window, or whose dim_content_item.published_at falls inside it. An item edited mid-window mixes two different questions into one accuracy figure.
- Filter attempt_no = 1 AND is_correct IS NOT NULL. Treating NULL is_correct as incorrect biases accuracy down by exactly the unscored rubric share, and that share is not stable week to week.
- Report accuracy with its denominator, plus removed_rows and removed_rows / raw_rows, so the size of the bug is visible next to the number it corrupted.
Worked solution (25 min)
- Run the ROW_NUMBER over the raw table and count rows with rn > 1, grouped by the within-partition submitted_at spread in seconds.
- Materialise the deduplicated CTE and record removed_rows.
- Build the eligible-item CTE from the version-change rule and the uses_adaptive_selection = FALSE join.
- Compute AVG(is_correct::int) over attempt_no = 1 rows on eligible items, and report it twice, once with and once without the version restriction.
Expected result: A deduplicated set where COUNT(*) equals COUNT(DISTINCT (learner_id, content_item_id, content_version_no, attempt_no)), a removed-row count with its share of raw rows, and one accuracy figure with its denominator over surviving first attempts on eligible items.
Verify it yourself
- Re-running the ROW_NUMBER over the deduplicated set produces no rn > 1.
- Every removed row sits inside a partition whose submitted_at spread is under the two-second threshold. A removal outside it means the partition key is wrong.
- If the version restriction moves accuracy by more than a point or two, one edited item carries a large share of the responses. Confirm which item that is before publishing either number.
Follow-up
- attempt_no is 1-based within learner and item, not within item version. If an item is edited between a learner's first and second attempt, which row is the first attempt on the new version, and does the metric want it?
- The retry bug fires more often on poor connections. If that population differs in accuracy, what does silently dropping their duplicates do to the number?
- How would you make this query cheap to leave in place after the bug is fixed, so it costs nothing on a clean table?
How would you approach a data problem with limited information?
Medium · product sense and metrics
Approach
- Name one primary metric, then the guardrail that stops it being gamed.
- Decompose the metric into the rates that drive it, and say which one you would check first.
- State what result would change your recommendation, so the answer is falsifiable.
Follow-up
- Which segment would you cut first, and what would that rule out?
- What would you do if the primary metric and the guardrail moved in opposite directions?
Present a real-world scenario and ask how you would analyze the data to draw conclusions.
Medium · product sense and metrics
Approach
- Decompose the metric into the rates that drive it, and say which one you would check first.
- Restate the decision this analysis has to support, and who acts on the answer.
- Name one primary metric, then the guardrail that stops it being gamed.
Follow-up
- How would you detect that the metric is being gamed rather than genuinely improving?
- Which segment would you cut first, and what would that rule out?
How do you prioritize your tasks when faced with multiple deadlines?
Medium · product sense and metrics
Approach
- Restate the decision this analysis has to support, and who acts on the answer.
- Fix the population and the time window before naming any metric.
- State what result would change your recommendation, so the answer is falsifiable.
Follow-up
- How would you detect that the metric is being gamed rather than genuinely improving?
- Which segment would you cut first, and what would that rule out?
How would you approach optimizing an existing data pipeline?
Medium · product sense and metrics
Approach
- Name one primary metric, then the guardrail that stops it being gamed.
- State what result would change your recommendation, so the answer is falsifiable.
- Fix the population and the time window before naming any metric.
Follow-up
- What would you do if the primary metric and the guardrail moved in opposite directions?
- How would you detect that the metric is being gamed rather than genuinely improving?
Describe your thought process when designing an experiment.
Medium · a/b testing and experimentation
Approach
- Decide the analysis before seeing data, including how long it runs and when you look.
- Name the randomisation unit first; it decides the variance and what the test can detect.
- Name the guardrails that would stop a launch even on a positive primary result.
Follow-up
- How would you handle interference between treated and control units?
- What would you conclude if the result is positive but the test is underpowered?
What is cross-validation, and why is it important?
Medium
Approach
- Work from the decision backwards to the evidence you would need.
- Say what you would check first and why it is the highest-information step.
- Clarify what is being asked and what a complete answer would contain.
Follow-up
- What assumption would you test first?
- How would you know your answer was wrong?
Decide whether a section-randomised rollout has a sample ratio mismatch
Easy · srm · randomisation · diagnostics
A four-week test randomised 800 class sections 50/50: 412 treatment, 388 control. The learner counts attached to those sections are 10,340 and 9,110. An analyst runs a chi-square on the learner counts, reports a sample ratio mismatch at p below 1e-15, and wants the readout blocked. Using dim_learner, fct_enrollment.section_id and the assignment log, state whether a sample ratio mismatch exists, which unit the test belongs on, and what the learner-level imbalance does and does not imply. Deliver a go/no-go with the statistic you ran.
Approach
- Run the chi-square goodness-of-fit at the unit that was actually randomised, which is sections: expected 400 per arm, observed 412 and 388. That is the only split with a known null under the randomiser.
- Reject the learner-level chi-square outright. Learners were never randomised, section sizes vary, so the learner split has no fixed 50/50 expectation and its p-value tests a hypothesis nobody assigned on.
- Quantify how much section-size variation alone explains: re-randomise the observed 800 section sizes 10,000 times and read where the observed 53.2% treatment share falls in that simulated null.
- If 53.2% sits outside the simulated null, look for a post-assignment filter. Restricting to learners with at least one activity row conditions on a post-treatment variable and creates real, non-random imbalance.
- Check the assignment log for sections whose id was re-created by roster_sync mid-test and for learners who changed section_id after assignment; either moves learners between arms.
- Give the go/no-go: release if the section-level test passes and the learner share sits inside the re-randomisation null, and say explicitly which test you are basing that on.
Worked solution (20 min)
- Compute the section-level chi-square: (412 - 400)^2 / 400 + (388 - 400)^2 / 400 = 0.36 + 0.36 = 0.72 on 1 degree of freedom.
- Read the p-value, about 0.40, and conclude there is no sample ratio mismatch at the randomised unit.
- Compute the learner share, 10,340 / 19,450 = 53.2%, and note the naive learner chi-square of 77.8 tests a split that was never randomised.
- Re-randomise the 800 observed section sizes 10,000 times, recording the treatment learner share each time.
- Compare 53.2% against the 2.5th and 97.5th percentiles of that distribution before writing the go/no-go.
Expected result: Section-level chi-square = 0.72, p is about 0.40, so there is no sample ratio mismatch. The 53.2% / 46.8% learner split is a section-size artefact unless the re-randomisation null rules it out, and the learner-level chi-square of 77.8 is invalid because learners were not the randomised unit.
Verify it yourself
- The section counts must sum to 800 and the expected cell must be exactly 400.
- The 1-degree-of-freedom critical value at alpha = 0.05 is 3.84; 0.72 clears it with room, so any conclusion of imbalance at the section level is arithmetic error.
- The re-randomisation null's mean learner share should sit near 50%. If it does not, the section-size distribution itself differs by arm and that, not the raw split, is the finding.
Follow-up
- The re-randomisation null puts 53.2% at its 99.7th percentile. What do you check next, and what would make you discard the test rather than re-run the analysis?
- How would you detect a sample ratio mismatch that appears only within one grade_band or one device_type?
- The randomiser is clean, but treatment sections carry 8% more learners with age_gated = TRUE. Does that block the readout, and what does it do to the metrics you can report?
First-attempt accuracy rose four points after a content release
Medium · psychometrics · mix-shift · adaptive-selection
First-attempt accuracy rose from 61 percent to 65 percent over the 28 days following a content release. You have fct_assessment_response (learner_id, content_item_id, content_version_no, objective_id, attempt_no, is_correct, submitted_at) and dim_content_item (content_item_id, version_no, irt_b, irt_a, calibration_n, status, published_at), plus a flag for whether each item was served by the adaptive selector. Determine how much of the four points, if any, is a change in learner performance. Deliver a corrected number with its restriction stated.
Approach
- Restrict to attempt_no = 1 and to (content_item_id, version_no) pairs that appear in both windows unchanged, then recompute the delta on that matched set. Editing an item changes what its historical responses mean, which is why the metric definition carries the version restriction rather than joining on content_item_id alone.
- Decompose the aggregate move rather than eyeballing it: with per-item accuracy a and response share w, write the delta as sum of w_pre * (a_post - a_pre) for the within-item term plus sum of (w_post - w_pre) * a_pre for the mix term, assigning the interaction explicitly so the two terms sum to the raw delta.
- Compare the response-weighted mean irt_b across the two windows, restricted to items with calibration_n at or above a stated floor. Items republished at a new version_no have irt_b NULL until they recalibrate, so they vanish from a difficulty-weighted mean and must be counted as their own bucket.
- Separate adaptive from fixed-form traffic and report them apart. A selector targeting a fixed success probability holds observed accuracy near that target by construction, so an adaptive accuracy series moves when the selector gets more conservative, not when learners improve.
- Publish only the fixed-form, version-stable number as the performance claim, and state the share of total responses it covers so the reader knows how much of the product it speaks for.
Follow-up
- Design a fixed-form measurement set that runs alongside the adaptive experience purely to produce a comparable accuracy series. What does it cost in learner time, and how often would you refresh it?
- How many responses do you want behind an item's irt_b before you will use that item in a difficulty-weighted comparison?
- An author rewrites one distractor in a multiple-choice item. Should version_no increment, and what breaks downstream if it does not?
Suggested practice checklist
Four days spend equal time on query work, statistics, modelling and product judgement at deliberately shallow depth, which produces a scored map of where you actually stand. The last three days spend everything on the two areas the role weights most, and close by re-running day one to measure movement.
Day 1 — Breadth pass: query fluency
- Solve six prompts spanning aggregation, joins, window functions and date arithmetic in 60 minutes total, stopping at 10 minutes each whether or not it works, and mark every prompt as solved, solved slowly, or stuck.
- For each unsolved prompt write the single blocking sentence (I lost the grain, I did not know the frame clause, I could not express the date boundary) instead of reading the solution.
- Translate one pandas transformation you know well into SQL and one SQL query into pandas, checking that both return the same row count and the same totals.
Deliverable: A scored six-row table, one line per prompt, saved for the day-seven re-run.
Day 2 — Breadth pass: statistics and inference
- Answer ten short questions in writing with nothing open: what a p-value is conditional on, what a 95 percent interval covers across repeated samples, when a paired test is the right one, what the bootstrap estimates, why multiple comparisons inflate false positives, how controlling the family-wise error rate differs from controlling the false discovery rate, what power depends on, what a missed real effect costs a product, the three situations where the central limit theorem does not rescue you (small n, very heavy tails, dependent observations), and what a standard error is the standard deviation of.
- Grade yourself against a reference and count only the answers that were exactly right, not the ones that were nearly right.
- Rewrite the two weakest answers the following morning from memory in full sentences.
Deliverable: Ten graded answers with an honest count of exact hits.
Day 3 — Breadth pass: modelling
- Take one tabular dataset end to end in 90 minutes: a leakage-safe split, a baseline that is not a model (majority class or historical mean), one regularized linear model, one gradient-boosted tree, and a single evaluation metric chosen before you look at any result.
- Write why that metric fits the cost structure: precision at a fixed recall for alerting, calibration for anything feeding a price or a threshold, ranking metrics for retrieval, and note that area under the ROC curve is insensitive to class balance in a way that can flatter a rare-positive problem.
- Name the leak you were most likely to introduce (an encoding fit on all rows before splitting, or a feature computed after the label's timestamp) and write the check that would have caught it.
Deliverable: A notebook whose first cell states the metric and the baseline, plus two lines on what beat what and by how much.
Day 4 — Breadth pass: product judgement
- Answer three case prompts aloud at 15 minutes each, timing how long passes before you state a success metric.
- For one case write the first segmentation you would run and the row counts you expect per segment, so that a tiny segment cannot quietly drive the conclusion.
- Take a metric definition you did not write, from a public dashboard, a textbook, or documentation you already have open, and list every place two analysts implementing it would diverge: which rows the denominator admits, whether the unit is an account or a person, what the time window is anchored to, and what happens to data that arrives late. Then write the one question that would close the largest of those gaps.
Deliverable: Three recorded case answers plus an ambiguity list for a metric someone else defined, ending in the single question you would ask about it.
Day 5 — Depth, first area
- Rank the four areas by how many bullet points in the role description each one covers, pick the top one, and spend the entire day inside it.
- Work the six hardest problems you can find in that area and for each write the generalizable move you should have reached for first, rather than the answer.
- Re-solve the two you failed the same evening with notes closed.
Deliverable: Six generalizable moves written as instructions to yourself, not as solutions.
Day 6 — Depth, second area, and the seam between them
- Repeat the depth protocol on the second-ranked area with the same six-problem structure.
- Construct one problem that requires both areas at once, for example a metric redefinition whose effect you must validate with a test whose readout you then have to query.
- Solve your own combined problem end to end and note where the handoff between the two areas cost you time.
Deliverable: One combined problem, solved end to end, with the handoff failure written down.
Day 7 — Integration and re-measurement
- Re-run the six prompts from day one under the same clock and compare both correctness and time.
- Run a 60-minute mixed mock that moves between areas without warning, since switching cost is what breadth passes do not train.
- Write the two areas you would still fail on, and the sentence you will use in the interview when you hit one of them.
Deliverable: A before-and-after score table plus a written plan for the two remaining gaps.
Getting an analysis acted on
Work that nobody used is a common and unflattering pattern in data careers, and interviewers probe for it. Have a story about an analysis that changed a decision, and be specific about how you got it in front of the person who could act. Also have one about work that went nowhere, with your reading of why.
Give an example of how you communicated complex data insights to a non-technical audience.
Medium · behavioural and stakeholder questions
Approach
- State the situation in two sentences and spend the rest on your reasoning.
- Close with what you would do differently, concretely.
- Quantify the outcome, including what you would not claim credit for.
Follow-up
- How did you know the outcome was caused by your change?
- What would you do differently if you ran that project again?
Tell an executive the usage report they publish is wrong
Medium · data quality · metric definition · stakeholder communication
A quarterly usage report an executive sends to district administrators counts an active learner as anyone with a fct_lesson_activity row in the quarter. You find two defects: accounts created by roster_sync that opened a single item during an automated import are counted in the numerator, and learners with age_gated = TRUE never reach the source table, so they are absent from the denominator. The report has already gone out twice. Deliverable: what you send, to whom, in what order, and what the definition should become. Probed: whether you can deliver an unwelcome data-quality finding without detonating it.
Approach
- Size the error before raising it. Recompute the metric both ways per org: 'the definition is wrong' and 'the number is overstated by 18 points on the largest account' get very different responses.
- Keep the two defects separate, because they push in opposite directions. Roster artefacts inflate the numerator while age-gated truncation shrinks the denominator, so the net error varies by org and a single average hides that.
- Go to the report owner first with the recomputation and a proposed replacement, not to their audience. The person who published it needs the chance to correct it themselves.
- Propose a definition that is defensible and computable today: distinct learners with at least one scored submission in the quarter, with enrollment_source in ('roster_sync','admin_bulk') excluded from activation cuts, and the age_gated share stated as a footnote rather than silently dropped.
- Say what should happen to the two reports already sent, with a recommendation and an owner. The restatement is the uncomfortable part, and leaving it for someone else to raise means the work is unfinished.
Follow-up
- The executive asks you to change the definition quietly from next quarter with no restatement. What do you do?
- How would you stop this class of defect reaching a published report again?
Account for an analysis you later discovered was wrong
Hard · postmortem · analytical rigor · ownership
Describe a case where you reported a result and later found it was wrong. Choose one where the error was yours and the number had already been used for a decision. Cover: the claim, the actual defect at the data or design level, how you found it, how long it had been live, who you told and in what order, and what you changed so the same class of defect cannot recur. The interviewer will push on the mechanism, not the apology. Probed: whether you understand your own failure modes well enough to have engineered around them.
Approach
- Pick an error with a nameable mechanism, such as a grain mistake, a survivorship filter, or a join that silently dropped age_gated learners. 'I misread a chart' has nothing testable in it.
- State the blast radius in decisions rather than in dashboards: what was decided, what was spent or promised, and to whom.
- Describe detection honestly, including whether someone else caught it and how long it ran undetected. A slow external catch is a usable answer; a vague one is not.
- Give the disclosure order and the reason for it: the decision owner first, with the corrected number and its direction in the opening sentence, then the wider audience.
- Close on the systemic fix and say whether it has fired since. A control that has never triggered on anything is a resolution, not a fix, and saying so is worth more than claiming otherwise.
Follow-up
- What did the corrected number change about the decision? If nothing changed, why did you escalate at all?
- Has the check you added caught anything since, and on what?
- What class of error would still get past you today?