The role as candidates describe it mixes three kinds of work: analysis that informs product and strategy decisions, predictive modelling for engagement and efficiency, and reporting through dashboards. The topics reported for the loop line up with that: machine learning fundamentals, model building, a data science case interview, a modeling case study and model evaluation metrics. Preparation therefore leans on modelling judgement (what to predict, how to validate, which metric fits the cost of errors) more than on puzzle-style algorithm drills.
The reported questions come in several shapes. Some are conceptual and short: supervised versus unsupervised learning, overfitting, feature selection, handling missing data. Some are small coding or SQL tasks, such as a function for the mean and median of a list or a query for the top three products by sales volume. Some are open case prompts, such as customer churn, predicting sales for a new product, cleaning a messy dataset or designing an A/B test for a new feature. A smaller group is about data systems: data quality at scale, real-time streaming, and relational versus NoSQL storage. Prepare each shape differently: a crisp definition with an example for the first, working code with edge cases for the second, and a structured walk to a recommendation for the third.
Candidates describe case analysis in three moves: define the problem, explore the data to find the key variables, and turn the findings into an action. Communication is also reported as an evaluation area, including explaining a complex model to a non-technical audience and saying which metrics show a model is succeeding. Pick one language (Python or R) and SQL as the tools you can write live, know what Tableau or Power BI would show for the KPIs you propose, and rehearse every answer out loud, because you will need to explain your reasoning as you work.
Modeling Case Study
reportedCandidates report this as the opening stage: a structured modeling case study where you show analytical skill. Model building, machine learning fundamentals and model evaluation metrics are among the topics reported for the loop, so prepare to carry a case from framing through to evaluation. Open by stating the target, the unit you predict for, the moment the prediction is made and the action the score would drive. Then cover features that exist at prediction time, a simple baseline, one or two candidate models, the metric, the validation scheme and what you would ship.
What to demonstrate
- Whether you frame the target, prediction time and decision before naming an algorithm
- Whether the metric and validation scheme match the cost of errors and the data's structure, such as a time-based split for forecasting
- Whether the case moves through a structure you announce and finish
How to prepare
- Write a reusable skeleton: target, unit, prediction time, features, baseline, model, metric, validation, failure modes, monitoring. Apply it to the new-product sales prediction and to customer churn.
- For regression and classification, list the metrics you would report and when each misleads: MAPE with zero-sales weeks, accuracy on imbalanced churn labels, AUC without calibration.
- On a public tabular dataset, fit a baseline and one stronger model in Python or R with a time-ordered split, and summarise the comparison in a single table.
Technical Interviews
reportedCandidates describe technical interviews, plural, that assess data science knowledge and skills. The reported areas are statistical analysis (hypothesis testing, p-values, confidence intervals), machine learning (regression, classification, clustering and their use cases) and data manipulation in Python, R or SQL. Questions of the conceptual, small-coding and SQL types in this guide are what you rehearse for this stage. Say your plan before typing: which table, what grain, which filter defines the population, then write the code.
What to demonstrate
- Statistical reasoning, including what a p-value and a confidence interval do and do not claim
- Working knowledge of regression, classification and clustering and when each applies
- Working code in Python, R or SQL for retrieving, cleaning and summarising data
How to prepare
- Write the mean-and-median function by hand: odd and even lengths, an empty list, unsorted input. State the cost of sorting versus a selection approach.
- Rehearse one-minute explanations of p-value, confidence interval, bias versus variance, regularisation and supervised versus unsupervised learning, each with a concrete example.
- Write the top-three-products-by-sales query three ways, with ROW_NUMBER, RANK and DENSE_RANK, and say how each treats ties. Then add a per-category version.
Case Studies
reportedCandidates say additional rounds may include case studies that test problem-solving. The reported shape of case analysis is problem definition, data exploration to find the key variables, and insight generation that ends in an actionable recommendation. Case-style prompts reported for this loop include customer churn, a messy dataset, deriving insights from a dataset, predicting sales for a new product and an A/B test for a feature. Turn the open prompt into a decision first, name the quantity that would settle it, state assumptions when you rely on them, and finish with a recommendation.
What to demonstrate
- A clear problem definition that is narrower than the prompt and still worth answering
- An exploration plan that finds the key variables and checks data quality before analysis
- A recommendation someone could act on, with the result that would reverse it
How to prepare
- Outline a churn case on one page: how churn is defined, the cohort view, candidate drivers, whether you would model it or run an experiment, and the intervention.
- Write a messy-data checklist (duplicate keys, units, impossible values, missingness pattern, outliers, time zones) and narrate it on a real public dataset.
- End every practice case with one closing sentence: the action, the result that supports it and the result that would change it.
Behavioral Evaluations
reportedCandidates describe the final stage as discussions about your experience and fit with the team. Reported evaluation areas include leadership, meaning influencing decisions and communicating with colleagues and stakeholders, plus culture fit. Reported scenarios in the loop include explaining a complex machine learning model to a non-technical audience and a time your communication cleared up a misunderstanding within a team. Prepare stories that carry numbers, and be ready to state the baseline, the period and the comparison behind each impact claim.
What to demonstrate
- Influence: how you persuaded a stakeholder or changed a decision with evidence
- How you handle team conflict and competing deadlines
- Whether you can explain technical work and its success metrics in plain language
How to prepare
- Write five stories in situation, action, result form: persuading a stakeholder, a difficult team dynamic, competing deadlines, a modelling project with real challenges, and a time your communication cleared up a misunderstanding.
- For each story with numbers, write the impact line as metric, value before, value after, period and how you attributed the change to your work.
- Prepare a three-sentence plain-language explanation of one model you built, then a version that adds the metric used to judge it.
PracHub editorial advice for the preparation topics above.
Naming an algorithm in the modeling case study before stating the target, prediction time and baseline
Open every modelling case with the label, the unit, the moment the prediction is made and the action the score drives. Then state a simple baseline (last period, group average or logistic regression) so any complex model has something to beat.
Judging a model with a default metric, such as accuracy on imbalanced churn labels or R-squared alone on a sales forecast
Tie the metric to the cost of each error type. For churn, discuss precision, recall and a threshold chosen with the retention team. For forecasts, report MAE or RMSE on a time-ordered holdout and say why MAPE fails when actuals can be zero.
Finishing a case study with a list of observations or "it depends"
Convert the prompt into a decision at the start, state assumptions at the point you use them, and close with the action, the number that supports it and the result that would reverse it.
Answering foundational questions with a single tactic: "fill with the mean" for missing data, "add regularisation" for overfitting
Give the diagnosis before the fix. For missing data, say which mechanism you suspect and how you would check it. For overfitting, show the train-versus-validation gap, then list remedies (more data, simpler model, regularisation, early stopping, feature pruning) with their costs.
Telling behavioral stories with impact figures that have no baseline, period or comparison, or explaining a model in jargon
Write each impact line as metric, before, after, period and attribution method, and concede where the link was correlational. Practise the plain-language model explanation until it needs no unexplained term.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
What is the time complexity of your favorite sorting algorithm?
What is the time complexity of your favorite sorting algorithm?
Approach
- Pick one and give the full profile. Merge sort is O(n log n) in the best, average and worst case, needs O(n) extra space and is stable. Quicksort is O(n log n) on average but O(n^2) in the worst case with bad pivots (randomised or median-of-three pivots make that unlikely), uses O(log n) expected stack space and is not stable.
- Mention what you actually call: Python's sorted and list.sort use Timsort, which is stable, O(n log n) in the worst case, O(n) on input that is already sorted, and uses up to O(n) extra memory. Heapsort is O(n log n) worst case with O(1) extra space but is not stable and is cache-unfriendly.
- Explain the lower bound. Any comparison sort needs Omega(n log n) comparisons in the worst case, because a decision tree must distinguish n! orderings and log2(n!) grows as n log n.
- Show when to beat it. Counting sort runs in O(n + k) for integer keys in a range of size k, and radix sort in O(d(n + k)), so neither is limited by the comparison bound. Insertion sort is O(n^2) in general but O(n + inversions), so it is fast on small or nearly sorted input, which is why Timsort uses it on short runs.
- Connect it to data work. For the top three products by sales you do not need a full sort: a heap of size k gives O(n log k), and in SQL ORDER BY with LIMIT lets the engine do a top-k sort.
Follow-up
- Why can no comparison-based sort beat n log n in the worst case?
- How would you sort a file far larger than memory?
- When does stability matter in practice? Give an example from sorting tabular data on multiple keys.
Measure the timesheet backfill curve and pick a reporting cutoff
time_entries has work_date (date), entered_at (timezone-aware UTC timestamp), hours and status. Given a snapshot_date, restrict to work_date in [snapshot_date - 180 days, snapshot_date - 60 days] so every cohort is fully observed. For k = 0..45, compute F(k): the share of a work_date cohort's final hours that already existed as of work_date + k days, pooled across cohorts. Return the 46-point curve and the smallest k with F(k) >= 0.99. Some rows are entered before the work date; those lags are real, not errors.
Approach
- Compute lag = (entered_at converted to the reporting timezone and taken as a date) - work_date in whole days, then clip negative lags to 0 instead of dropping them; leave and planned time are routinely entered ahead of the work date and dropping them deflates the early curve.
- Take cohort totals as groupby(work_date).hours.sum() over the restricted window. These are final only because the window stops 60 days short of the snapshot, which is why the restriction is in the prompt.
- Build the numerator by summing hours per (work_date, lag), sorting by lag, taking a per-cohort cumsum, then reindexing each cohort onto the full 0..45 lag grid and forward-filling, so a cohort with no entries at a given lag holds its previous level rather than disappearing.
- Pool as sum(numerators) / sum(denominators) at each k, not as the mean of per-cohort shares. Holiday weeks are tiny cohorts and would otherwise carry the same weight as a full week.
- Read k* off the pooled curve and report F(45) with it: if F(45) is below about 0.995 the tail runs past the grid and k* is a lower bound, not the answer.
Follow-up
- The dashboard refreshes daily. Would you hold the window back past k*, or publish an as-of-entered_at series instead, and what does each choice cost the reader?
- One practice area has a tail twice as long as the rest. Does that change the firm-wide cutoff, or does it change what you publish per practice area?
Simulate the chance a capped engagement crosses its cap
A capped time-and-materials engagement has not_to_exceed_usd = 400000, has billed 250000 to date, and bills at a blended bill_rate_usd of 250. Fourteen delivery weeks remain before planned_end_date. You have that engagement's last twenty weekly totals of approved billable hours as a pandas Series. Estimate the probability that cumulative billable value crosses the cap before the planned end, and the expected unbillable hours if it does. Resample the observed weeks; do not assume normality. Report a Monte Carlo standard error and justify the number of draws.
Approach
- Reduce the deterministic part first: the cap still affords (400000 - 250000) / 250 = 600 hours, so the whole question is the distribution of the sum of fourteen future weekly hour totals against a fixed threshold of 600.
- Before resampling, check the twenty observed weeks for trend and lag-1 autocorrelation. Independent resampling is defensible only if the weeks are exchangeable; on a ramping engagement use a moving-block bootstrap or model the ramp, because i.i.d. draws understate the upper tail, which is exactly the tail the question is about.
- Draw one (B, 14) array with np.random.default_rng().choice(observed, size=(B,14), replace=True), sum along axis 1, and compute p_hat = mean(total > 600) in one vectorised pass.
- Report expected unbillable hours two ways: unconditional mean(maximum(total - 600, 0)) for expected loss, and the mean conditional on a breach for how bad a breach is when it happens. The second is the number that drives a change-order conversation.
- Attach se(p_hat) = sqrt(p_hat(1 - p_hat)/B) and pick B from the precision you need: plus or minus one point at 95% confidence needs about 1.96^2 * 0.25 / 0.01^2, roughly 9600 draws at the worst case p = 0.5.
- State the assumptions that would flip the answer: constant blended rate, no scope change, no holiday weeks inside the fourteen, and a cap that applies to fees rather than to fees plus expenses.
Worked solution 30 min
- affordable_hours = (400000 - 250000) / 250 = 600.0; print it, because a wrong threshold makes every later number wrong in a way no simulation reveals.
- Plot or regress the twenty weekly totals against week index and compute lag-1 autocorrelation; record the result as the stated justification for i.i.d. versus block resampling.
- rng = np.random.default_rng(7); draws = rng.choice(weekly.values, size=(10000, 14), replace=True); totals = draws.sum(axis=1).
- p_hat = (totals > 600).mean(); se = np.sqrt(p_hat * (1 - p_hat) / 10000); overrun = np.maximum(totals - 600, 0); report overrun.mean() and overrun[totals > 600].mean().
- Re-run with a second seed and confirm p_hat moves by less than two standard errors before reporting.
Follow-up
- Hours past the cap still cost money. Restate the result as expected gross margin rather than a probability.
- Two weeks of time are entered but not yet approved. How do you fold them in without double-counting?
- A change order that raises the cap is judged 60% likely. How does that change the number you present, and to whom?
Write a function to calculate the mean and median of a list of numbers…
Write a function to calculate the mean and median of a list of numbers.
Approach
- Settle the contract first: what an empty list returns (I raise ValueError, as Python's statistics module raises StatisticsError, a ValueError subclass), and how None or NaN values are treated. A NaN that is silently sorted can return a wrong median, so I filter it or raise.
- Mean: sum divided by length, one pass, O(n). For long float lists, math.fsum reduces rounding error compared with a plain sum.
- Median: sort a copy (sorted, not list.sort, so the caller's list is not mutated). For odd n take the middle element; for even n average the two middle elements. That costs O(n log n) time and O(n) extra space.
- If asked to do better: quickselect finds the median in O(n) average but O(n^2) worst case, and median-of-medians guarantees O(n) worst case with a large constant. For a stream, keep a max-heap of the lower half and a min-heap of the upper half: O(log n) per insert and O(1) per median query.
- Test the edge cases out loud: one element, even and odd lengths, negatives, duplicates, and an already sorted input. In SQL the same median is PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY x) in PostgreSQL, and AVG ignores NULLs, which changes the denominator.
Follow-up
- Numbers arrive one at a time and you need the running median after each one. How do you do it?
- Compute the median per group in SQL on an engine without PERCENTILE_CONT.
- The list has a billion values and does not fit in memory. How do you get the median, exactly or approximately?
What are the trade-offs between using a relational database versus a N…
What are the trade-offs between using a relational database versus a NoSQL database?
Approach
- Frame the answer by workload, not by preference. Relational databases give a fixed schema, constraints, joins and multi-row ACID transactions, which suit transactional data with many relationships and ad hoc SQL. NoSQL stores trade some of that for horizontal scale and a flexible schema.
- Name the NoSQL families, because they differ: key-value (Redis, DynamoDB), document (MongoDB), wide-column (Cassandra) and graph (Neo4j). Each is designed around known access patterns, usually with denormalised data and few or no joins.
- Cover consistency accurately. Many NoSQL systems default to or offer eventual or tunable consistency (Cassandra lets you set consistency per query; DynamoDB reads are eventually consistent unless you request strong reads). Transaction support varies: MongoDB has multi-document transactions since 4.0, while others limit atomicity to a single item. Under a network partition, CAP forces a choice between consistency and availability.
- Add the analytics angle a data scientist owns. Neither an OLTP relational database nor a document store is the right place for heavy aggregation; analytical queries usually run in a columnar warehouse fed by ETL, where SQL works well regardless of the source.
- Close with a decision rule: relational when integrity, joins and ad hoc querying matter; a NoSQL store when access patterns are known, write volume or scale-out dominates, or the schema changes often. Note that many systems use both.
Follow-up
- Clickstream events need storing for later analysis. Which store would you pick for ingestion and which for analysis, and why?
- A dashboard reads from an eventually consistent replica. What could a stakeholder see that would confuse them?
- How would you model a many-to-many relationship in a document store, and what does it cost you?
Engagement margin without fan-out across two fact tables
fct_engagement holds engagement_id, pricing_model and contract_value_usd. fct_invoice_line holds engagement_id, line_type, amount_usd and status. fct_time_entry holds engagement_id, hours, cost_rate_usd, is_billable and status. For engagements closed last year, return fees (line_type IN ('fees','milestone','credit_note') and status <> 'draft'), delivery cost (SUM(hours * cost_rate_usd) over approved entries, billable and non-billable alike) and gross margin, grouped by pricing_model. A single SELECT joining the engagement to both fact tables and then aggregating produces wrong numbers: say what the error is, then write the correct query.
Approach
- Do the arithmetic out loud. An engagement with 40 qualifying invoice lines and 900 approved time entries yields 36,000 rows on the double join: SUM(amount_usd) comes back 900 times too large and SUM(hours * cost_rate_usd) 40 times too large. The two inflation factors are different, so the ratio moves too — per engagement the double join replaces the cost-to-fee ratio with (cost / fees) * (line count / entry count), so a true 30 percent margin reads as 1 - 0.7 * (40 / 900), about 97 percent.
- Know which shape of this bug actually survives review. The ratio is preserved only where an engagement carries the same number of qualifying invoice lines as approved time entries, and then only as a row-count-weighted margin, 1 - SUM(cost_i * k_i) / SUM(fees_i * k_i), which still differs from the true pooled margin unless k_i is constant across engagements. So you get either a total absurd enough to tempt someone into a scaling patch, or, on a population where the two counts happen to track each other, a believable-looking ratio sitting on fees and cost that are each wrong by orders of magnitude.
- Aggregate each fact table to engagement grain in its own CTE, then LEFT JOIN both onto fct_engagement. One row per engagement then holds by construction rather than by inspection.
- Include non-billable delivery hours in cost. Rework, unbilled travel and pursuit time on a live account are real fully-loaded cost, and excluding them flatters fixed-fee work specifically, which is the mix you most need to see clearly.
- Treat zero and NULL as different: an engagement with no invoice lines has undefined margin, not zero. Divide by NULLIF(fees, 0) and keep those engagements in a labelled bucket instead of letting an inner join hide them.
- Group by pricing_model before reporting any firm-wide figure, and publish the fee mix next to it. Fixed-fee margin falls as hours rise, uncapped time-and-materials margin does not, so a shift in what was sold moves the pooled number with no change in delivery at all.
Worked solution 30 min
- Compute standalone control totals: total fees over the filtered invoice-line set and total cost over the approved time-entry set, both for the closed-engagement population.
- Build fees_by_engagement and cost_by_engagement as separate CTEs at engagement grain.
- LEFT JOIN both onto fct_engagement, compute margin with NULLIF on the denominator, and group by pricing_model.
- Run the naive double join on a single engagement and confirm its fee total equals the true total times that engagement's time-entry count, and its cost total the true cost times its invoice-line count.
- Report the fee mix by pricing_model alongside the margin column.
Follow-up
- Decompose a period-over-period margin move into a within-pricing-model component and a between-model mix component, and show the two sum to the total.
- Where does not_to_exceed_usd change the time-and-materials picture, and how would you find engagements that crossed it?
- Roll this up to the account through parent_client_id. What must the recursive CTE guard against?
How do you prioritize your work when facing multiple deadlines?
How do you prioritize your work when facing multiple deadlines?
Approach
- Open with a rule you can state in one line. Mine is to rank work by the cost of it slipping (who is blocked, what decision waits on it, whether the date is hard) and then by effort. Then show the rule applied to a real week, not in the abstract.
- Make the triage concrete. Name the competing deliverables (say a model refresh, a stakeholder dashboard and an ad hoc analysis), what each one fed, and which you moved and why.
- Show that you renegotiate scope early and in the open. Tell the owner of the deprioritised item as soon as you know, and offer a smaller version by the original date or the full version later, rather than missing the deadline quietly.
- Explain how you protect the analysis itself under pressure. Cut scope, such as fewer segments or a simpler model, rather than skipping validation, and say what you labelled as provisional.
- Close with the outcome and what you changed afterwards. The answer that sinks you is a generic task-list habit with no trade-off and no stakeholder in it.
Follow-up
- Tell me about a time you got the priority call wrong. What did it cost, and what did you change?
- Two stakeholders both say their request is the most urgent. How do you decide, and who makes the final call?
- How do you handle a request that arrives mid-sprint and would push out committed work?
If tasked with predicting sales for a new product, what factors would …
If tasked with predicting sales for a new product, what factors would you consider?
Approach
- Pin down the target before the factors: unit sales or revenue, which channel and region, which horizon (launch month or first year), and what decision uses the forecast, such as inventory, staffing or a go/no-go. The required precision depends on that decision.
- There is no history for a new product, so borrow it. Use analogous past launches matched on category, price band and channel, or a model pooled across products that predicts from product attributes (price, category, features, distribution breadth, marketing spend), so the new item inherits information from similar ones.
- List drivers by group: the product itself (price relative to substitutes, features), go-to-market (distribution coverage, promotion, launch timing), demand context (seasonality, market size, macro conditions) and cannibalisation of existing products. For adoption curves, the Bass diffusion model separates market size m, innovation p and imitation q.
- Watch for censored demand. Units sold during a stockout understate demand, so flag or model stockout periods before you fit anything to early sales or to analog launches.
- Report a range, not a point: prediction intervals or scenarios. Backtest the method on past launches with a scale-free error such as MAPE or WAPE, then update the forecast as the first weeks of real sales arrive, for example by reweighting analogs or using Bayesian updating.
Follow-up
- The first two weeks of sales come in 40 percent below your forecast. How do you tell whether to revise the curve or wait?
- How would you pick the analogous products, and how would you guard against picking the ones that happen to agree with you?
- How would you estimate how much of the new product's sales are cannibalised from existing ones?
How do you stay updated with the latest trends in data science?
How do you stay updated with the latest trends in data science?
Approach
- Name two or three specific, recurring sources and why each earns your time: library release notes for the tools you use daily (pandas, scikit-learn, your SQL engine), a few practitioner blogs or newsletters, and papers or conference talks in your area. A vague 'I read a lot' sounds identical from every candidate.
- Describe your filter. Reading a technique is not adopting it: I reproduce it on a small dataset or a past problem and compare it with what I already use before I suggest it to a team.
- Give one concrete example of something you learned and applied, with the measured result. For example, a new validation scheme or feature-selection method, the baseline it replaced, and what changed in the metric or in time saved.
- Tie it to the work this role lists: Python or R, SQL, and visualisation in Tableau or Power BI, with cloud and Spark as nice-to-haves. Keeping current on the tools you ship with counts as much as following research headlines.
- Avoid name-dropping trends you have not used. Saying you are evaluating something and have not yet used it in production is stronger than implying hands-on experience you cannot back up.
Follow-up
- What is something recent you decided not to adopt, and why?
- Walk me through the last technique you picked up. How did you check it actually beat what you had?
- How do you share what you learn with your team?
Given a dataset, outline your process for deriving insights.
Given a dataset, outline your process for deriving insights.
Approach
- Start from the decision. Ask what question the dataset should answer, who acts on it and what would change, so the exploration has a target instead of becoming a tour of every column.
- Audit before you analyse. Establish the grain (what one row means), confirm key uniqueness, count rows against a known total, check date ranges, null rates, duplicates and impossible values, and note how the data was collected, because selection bias lives there.
- Profile, then compare. Look at univariate distributions and outliers, then cut the key metric by the segments likely to matter (time, cohort, region, product). Decompose a headline metric into its component rates so you can see which one moved.
- Keep claims honest. Say which findings are descriptive and which would need an experiment or a quasi-experimental design to be causal, and if you slice many segments, treat a single significant one as a lead to confirm, not a result (multiple comparisons).
- Finish with a recommendation: the finding, its size with uncertainty, the action, and what result would reverse it, in a chart or dashboard a non-technical stakeholder can read.
Follow-up
- You find a striking pattern in one segment. How do you check it is not noise or an artefact of how the data was collected?
- The data has no documentation and the owner has left. What do you do first?
- How would you decide that the analysis is done?
Describe how you would design an A/B test for a new product feature.
Describe how you would design an A/B test for a new product feature.
Approach
- State the hypothesis and the decision: what the feature should change, one primary metric tied to it, a minimum detectable effect worth shipping, and guardrail metrics (latency, errors, revenue, retention) that block launch even if the primary metric wins.
- Choose the randomisation unit, usually the user, with stable hashing so assignment does not flip between sessions. Analyse only users who reach the feature's exposure point. If users interact with each other (shared accounts, marketplaces), randomise by cluster or use a switchback design instead.
- Size the test before launch. For a two-arm test, n per arm is about 2 (z for 1 minus alpha/2 plus z for power) squared times sigma squared, divided by delta squared, with p(1 minus p) as the variance for a binary metric. Convert that to days of eligible traffic and run whole weeks to cover weekly seasonality.
- Pre-commit the analysis: a two-proportion z-test or Welch t-test for the primary metric, the delta method or a user-level bootstrap for ratio metrics like clicks per session, a sample ratio mismatch check (chi-square against the intended split) before reading any result, and no stopping early on a peek unless a sequential method is used.
- Read the result with its confidence interval, check guardrails and pre-declared segments, and look at the effect against days since first exposure to separate a novelty effect from a lasting one. End with ship, iterate or stop.
Follow-up
- The split came out 50.8/49.2 on two million users. Is that a problem, and what do you check?
- The primary metric is flat but a secondary metric is significant. What do you recommend?
- The feature changes how users interact with each other, so user-level randomisation leaks. How do you redesign the test?
How would you ensure data quality in a large-scale data processing sys…
How would you ensure data quality in a large-scale data processing system?
Approach
- Define quality as checkable properties: completeness (row counts and null rates), validity (types, ranges, allowed values), uniqueness (primary keys, no duplicate events), consistency (referential integrity, totals reconciling across tables), timeliness (data fresh by a set time) and accuracy against a trusted source.
- Enforce checks at each stage. At ingestion, validate against a schema contract and send failing records to a quarantine or dead-letter table rather than dropping them. After transformation, run assertions on keys, row-count reconciliation against the source and aggregate totals, using a framework such as dbt tests or Great Expectations, or plain SQL checks.
- Decide which checks block and which warn. A duplicate primary key or a failed reconciliation should stop publication to downstream dashboards and models. A modest shift in a null rate should alert an owner. Every check needs a named owner and a runbook.
- Handle the failure modes of distributed pipelines: at-least-once delivery creates duplicates, so dedupe on an event id and make jobs idempotent so reruns do not double-count. Late events need a watermark or a backfill window (Spark Structured Streaming supports watermarks), and reporting should only treat a period as final once that window has closed.
- Monitor what static rules miss. Track daily volumes and distribution statistics per source with seasonality-aware thresholds to catch silent drift, and keep lineage so a bad upstream table can be traced to every report and model it feeds.
Follow-up
- A blocking check fails overnight and a stakeholder needs the dashboard in the morning. What do you do?
- How would you detect a bug that changes values without changing row counts or schemas?
- How do you stop a model in production from quietly training on corrupted data?
Measure a staggered process rollout across five practice areas
A delivery-review process was rolled out one practice area at a time over six quarters, and all five practice areas now have it, so there is no never-treated group. You have engagement-quarter gross margin reconstructible from fct_invoice_line and fct_time_entry, plus pricing_model on fct_engagement. Leadership wants the effect on margin. Explain why a two-way fixed effects regression of margin on a treated indicator is not trustworthy here, name the estimator you would use instead and what identifies it, and specify how you would obtain a defensible p-value from five clusters.
Approach
- Explain the two-way fixed effects failure concretely. Under staggered timing the coefficient is a weighted average of every available two-by-two comparison, and that set includes comparisons that use already-treated units as controls for later-treated ones. Those comparisons difference out not only the common time shock but also the earlier cohort's ongoing treatment-effect growth, so when effects grow after adoption the aggregate is pulled toward zero and can flip sign. Decomposed onto the underlying ATT(g,t), the implied weights can be negative, which is why the coefficient is not an average of treatment effects at all. This is a bias in the estimand, not a small-sample artefact, so more data does not fix it.
- Switch to a heterogeneity-robust estimator: Callaway and Sant'Anna group-time ATT(g,t) using not-yet-treated units as the comparison group, aggregated into an event-study path and a single summary. Sun and Abraham's interaction-weighted estimator or Borusyak-Jaravel-Spiess imputation answer the same objection. With every area eventually treated, identification rests entirely on not-yet-treated windows, so the last-adopting area carries disproportionate weight; say that out loud rather than burying it.
- Test parallel trends honestly. Plot event-time leads with confidence intervals and refuse to read a non-rejection as confirmation, because at five clusters that test is badly underpowered. Pair it with a sensitivity analysis that bounds the post-treatment violation as a multiple of the largest pre-period violation and reports the multiple at which the conclusion breaks.
- Fix the inference, and be precise about what the bootstrap can deliver at five clusters. Five sits far below the roughly forty at which cluster-robust standard errors become approximately valid, and below that they are sharply downward-biased. A wild cluster bootstrap with Rademacher weights draws from 2^5 = 32 sign vectors, but the null-imposed bootstrap t-statistic is odd in the sign vector: negating every weight negates t* and leaves |t*| unchanged, because the coefficient deviation is linear in the weights while the cluster-robust variance is quadratic in them. The 32 vectors therefore collapse to 2^4 = 16 distinct values of |t*|, so the smallest attainable two-sided p-value is 1/16 = 0.0625. That is above 0.05, so at five clusters a Rademacher bootstrap cannot reject at the conventional level however large the true effect is. Use Webb six-point weights, whose 6^5 = 7,776 vectors collapse to 3,888 distinct |t*| and a floor near 0.00026, or randomisation inference permuting the five observed adoption dates across the five practice areas, which gives 5! = 120 assignments and a floor of 1/120 = 0.0083.
- Deal with the mix confound before reporting anything. Fixed-fee margin falls with hours worked while uncapped time-and-materials margin rises with them, so a rollout that coincided with a pricing-mix shift contaminates the pooled estimate. Estimate within pricing_model and report the within-model effects alongside the mix decomposition.
Worked solution 45 min
- Build the engagement-quarter panel with an adoption quarter per practice area, keyed on the quarter the process went live rather than when it was announced.
- Run the Goodman-Bacon decomposition of the two-way fixed effects estimate and read off how much of the total weight sits on already-treated-as-control comparisons; that share is the diagnostic there, since those weights are non-negative by construction. For negative weights on the underlying ATT(g,t), run the de Chaisemartin and D'Haultfoeuille decomposition and report the negative share.
- Estimate ATT(g,t) with not-yet-treated controls, aggregate to event time, and plot leads and lags with confidence bands.
- Compute the p-value three ways, cluster-robust, Rademacher wild bootstrap and Webb wild bootstrap, and report the Webb figure while noting that the Rademacher floor at five clusters is 1/16 = 0.0625 and therefore cannot clear 0.05 at all.
- Re-estimate separately for fixed_fee and time_and_materials engagements and report the mix decomposition against the pooled change.
Follow-up
- If the rollout order was not random, say the worst-performing practice area went first, what does that do to parallel trends and what would you do about it?
- How would you choose between a synthetic control built on a single practice area and the group-time estimator?
- What would the event-study path have to look like for you to believe the effect is real rather than a continuation of a pre-existing trend?
Days sales outstanding improved while collections got worse
A cash dashboard reports mean days-to-pay as AVG(paid_at - issued_at) over fct_invoice_line where status = 'paid'. It improved from 47 to 39 days last quarter. The finance lead insists collections are worse, and invoice volume rose about 30% after a large batch issued early in the quarter. Using invoice_line_id, engagement_id, issued_at, due_date, paid_at, status and amount_usd, explain the contradiction and deliver the estimate you would report instead, with its assumptions.
Approach
- Name the bias precisely: at any snapshot, the set of paid invoices over-represents fast payers, because slow ones have not finished yet. Unpaid, partially paid and disputed lines are right-censored observations, not absent ones, and averaging over completions alone is biased downward.
- Explain why the bias grew: a large young cohort adds many invoices whose slow half cannot yet appear in the paid set, so a volume increase alone pushes the naive mean down even with unchanged payment behaviour.
- Build the censored dataset: event time = paid_at - issued_at for paid lines; censoring time = snapshot_date - issued_at for status IN ('issued','partially_paid','disputed'). Confirm no placeholder dates were substituted for NULL paid_at.
- Estimate with Kaplan-Meier by issue-month cohort and report both the median and the restricted mean to a fixed horizon such as 90 days, so cohorts of different maturity are compared over the same span. State the independent-censoring assumption: censoring here is administrative, driven by issue date rather than by payment behaviour, which is what makes it defensible.
- Cross-check with a metric that needs no model: share of each cohort's invoiced amount collected by day 30, 60 and 90. If the recent cohort's curve sits below prior cohorts at the same age, collections really did deteriorate.
- Report amount-weighted as well as count-weighted, since one large disputed invoice moves cash without moving the count.
Follow-up
- Disputed invoices may never pay at all. Does that break the censoring assumption, and how would you handle it?
- How would you turn this into a weekly operational report that cannot be gamed by issuing more invoices?
- Proposal cycle time has the same structure. What is the equivalent fix there?
The week follows the reported stages: a modelling case first, then ML fundamentals, coding and SQL, statistics and A/B tests, case studies, data systems, and finally behavioral stories. Each day ends with an artifact you can reread before the loop.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Frame a modeling case from target to metric
- Write a reusable skeleton: target, unit, prediction time, features, baseline, model, metric, validation, monitoring.
- Apply it to predicting sales for a new product. List the factor groups you would consider (price, promotion, seasonality, channel, comparable past launches, cannibalisation of existing products) and say how you would forecast with no history, such as by borrowing from analog products.
- Choose a metric and a time-ordered validation scheme for that forecast and justify both in two sentences.
Deliverable: A one-page skeleton filled in for the new-product sales prediction, ending with the chosen metric and validation split.
Practice prompt ↗Worked solution ↗02ML fundamentals and evaluation metrics
- Write a comparison of supervised and unsupervised learning with one use case each, and list regression, classification and clustering methods with when each applies.
- Build a metrics sheet: MAE, RMSE, R-squared and residual plots for regression; precision, recall, F1, ROC AUC, PR AUC and calibration for classification, each with a situation where it misleads.
- Implement the split search of a decision tree from scratch in Python (Gini impurity, best threshold per feature, recursion with a depth limit) and compare it with a library tree on a small dataset.
- Write the overfitting answer: how to see it (train versus validation gap) and five remedies with their costs, plus filter, wrapper and embedded feature selection.
Deliverable: A notebook with the from-scratch tree, plus a written supervised-versus-unsupervised comparison, an overfitting and feature-selection write-up, and a one-page sheet of metrics and when each fails.
03Coding and SQL under narration
- Write the mean-and-median function with tests for odd length, even length, one element, empty input and unsorted input. State the complexity of the sorting version and of a selection-based alternative.
- Write a short table comparing merge sort, quicksort, heapsort and insertion sort on worst case, memory, stability and nearly-sorted input, so you can answer the favourite-sorting-algorithm question for any choice.
- Write the top-three-products-by-sales query with ROW_NUMBER, RANK and DENSE_RANK, then a per-category version. Then work the PracHub drill on avoiding fan-out across two fact tables, narrating the plan before you type.
Deliverable: A tested function, a one-page sorting comparison and a SQL file with three ranking variants plus the drill solution.
Practice prompt ↗Practice prompt ↗Practice prompt ↗04Statistics, A/B tests and messy data
- Write explanations of the p-value and the confidence interval in plain language, including one common misreading of each.
- Design an A/B test for a new product feature: randomisation unit, primary metric, guardrail metrics, the sample-size formula for a binary metric, the decision rule and what you would do if the result is flat.
- Work through a messy dataset in Python or R: check key uniqueness, types and units, impossible values and the missingness pattern, then write what you did about each and why.
- Answer the missing-data question out loud using mechanism, method and a sensitivity check.
Deliverable: A one-page test design with a sample-size calculation, a cleaning log of each issue and decision, a half-page of p-value and confidence-interval explanations, and a short written outline of your missing-data answer.
Practice prompt ↗Practice prompt ↗Practice prompt ↗Worked solution ↗05Case studies that end in a recommendation
- Outline a customer churn case: churn definition, cohort retention view, candidate drivers, model versus experiment, and the intervention you would recommend.
- Practise the metric-diagnosis case in the PracHub drill where days sales outstanding improved while collections got worse. Name the decomposition you would run first.
- Work the PracHub drill on a staggered rollout across practice areas, and write the identifying assumption and the strongest threat to it.
- For each case, write the closing sentence: action, supporting number, reversing result.
Deliverable: A churn case outline, a written diagnosis for the metric drill, and a rollout memo, each ending in a recommendation sentence.
Practice prompt ↗Practice prompt ↗06Data systems and reporting
- Write a data-quality plan for a large processing system: schema checks, freshness, row-count and null-rate monitors, uniqueness and referential checks, distribution drift, and where each check runs.
- Prepare the relational versus NoSQL answer for an analytical workload: joins, schema flexibility, consistency, query patterns and scale.
- Sketch a KPI dashboard in Tableau or Power BI for a product you know, defining each metric's numerator, denominator and refresh logic.
- Outline two designs candidates report. Streaming: source, broker such as Kafka, stream processor with watermarks, sink and late-data handling. Model deployment: batch versus online serving, feature parity between training and serving, model registry, canary rollout and drift monitoring.
Deliverable: A data-quality checklist, a relational-versus-NoSQL comparison table, a dashboard sketch with metric definitions, and a one-page streaming and model-deployment outline.
Practice prompt ↗Practice prompt ↗07Behavioral stories and a full mock
- Finalise five stories: persuading a stakeholder, a difficult team dynamic, competing deadlines, a modelling project, and a time your communication cleared up a misunderstanding. Write an impact line (metric, before, after, period, attribution) for each that has numbers, and test the persuasion story against the PracHub drill on defending an impact claim without randomisation.
- Write short answers to the prioritisation, motivation and staying-updated questions, each with specifics: how you rank competing deadlines, a named source you follow and something you tried because of it.
- Deliver the plain-language model explanation to a friend outside data and ask them to repeat it back.
- Run a mock of a case followed by two technical questions, speaking throughout.
Deliverable: Five written stories with impact lines, three short answers, the plain-language model explanation as tested on a friend, and a mock recording with the places you went silent marked.
Practice prompt ↗Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
Candidates describe the behavioral stage as a discussion of experience and team fit, with leadership defined as influencing decisions and communicating with colleagues and stakeholders. For a data role, that means stories where an analysis or model changed a decision, with the measurement attached, and an explanation of technical work that a non-technical listener can follow. Rehearse the reported prompts first.
How do you handle missing data in a dataset?
How do you handle missing data in a dataset?
Approach
- Start by measuring the gap: missing share per column, per segment and over time, and whether a NULL means unknown, not applicable or zero events logged. A structural NULL (a field that does not exist for that user type) should become its own category or be left alone, not imputed.
- Classify the mechanism: missing completely at random, at random given observed columns, or not at random (high earners skipping an income field). Test it by comparing other variables between rows with and without the value, or by fitting a quick model that predicts the missing flag. MNAR cannot be proven from the data, so say so and run a sensitivity check.
- Choose by purpose. For a small MCAR share, dropping rows is unbiased but costs power. For prediction, impute with the median or mode plus a missing-indicator column, KNN or iterative imputation, or use a tree-based model that accepts NaN natively. For inference, use multiple imputation so standard errors carry the imputation uncertainty; mean imputation shrinks variance and weakens correlations.
- Keep the imputer inside the pipeline: fit it on training folds only (a scikit-learn Pipeline inside cross-validation, or the R equivalent) and reuse the fitted values at serving time. Fitting on the full dataset leaks information, and a column rarely missing in training but often missing in production needs its own handling.
- Close with your own example: the column, how much was missing, the mechanism you found, the method you chose, and a comparison of results under deletion versus imputation showing the conclusion held.
Follow-up
- How would you check whether values are missing at random, and what could you not rule out?
- Why is mean imputation a problem for a regression coefficient or a variance estimate?
- The column is rarely missing in training data but often missing in production. What do you change?
Defending your own impact claim without randomisation or clean units
At your review you plan to claim that the realisation dashboard you built recovered 1.4 million dollars. The evidence is that engagement-month realisation rose four points over two quarters among engagements whose leads used it. Adoption was voluntary. There are about sixty client accounts and the top five carry most fees. A new rate card shipped in the same quarter. Write the claim you can defend, the estimate you would actually produce, and what you say when asked for a causal number you cannot get.
Approach
- Name the probe: whether you can separate the number you want from the number the data supports, under review pressure, without either inflating it or retreating to saying nothing can be known.
- State both identification problems concretely. Voluntary adoption means adopting leads are plausibly the ones who already manage realisation, so the comparison is confounded at the person level. The rate card changes bill_rate_usd, which sits in the realisation denominator, so part of the four-point move is arithmetic rather than behavioural.
- Neutralise what you can. Recompute realisation with bill rates snapshotted on work_date, or hold the denominator at the old rate card, so the rate-card change cannot move the metric by construction. Then rerun the comparison.
- Get the inference right for the unit count. Cluster at client_id, not engagement, because engagements in one account share a partner, a rate card and a team. With sixty accounts and five carrying most fees, the effective cluster count is far below sixty, so report a wild cluster bootstrap interval rather than plain cluster-robust standard errors, which are biased downward in that regime.
- Report both weightings and explain the divergence: an account-weighted estimate describes the typical account, a value-weighted one describes the revenue, and if they disagree a small number of accounts is carrying the result. Then give the decision-relevant sentence: the defensible range, whether its lower bound still clears the build cost, and what a proper staggered rollout would have bought.
Follow-up
- The pre-period trends for adopters and non-adopters are not parallel. What do you report then?
- You get to design the next rollout. What do you change so the same question is answerable, without randomising individual accounts?
Disagreeing with a proposed utilisation target using realisation evidence
A delivery lead proposes raising the billable utilisation target for analyst through senior_consultant from 72 to 85 percent. You have fct_time_entry, including is_billable, bill_rate_usd and written_off_hours, and fct_invoice_line. You believe the target will raise reported utilisation and lower fees. Prepare the disagreement: the evidence you pull, the mechanism you name, the metric pair you propose instead, and the condition under which you would concede that the target is correct.
Approach
- Name the probe: whether you disagree with a mechanism and a measurement, or with an opinion about a metric being bad.
- State the substitution precisely. Utilisation counts approved hours with is_billable = TRUE. An hour that is charged to the client and later written off stays in that numerator, so utilisation is unaffected while realisation, fees divided by hours times bill_rate_usd, falls and margin falls with it. That is the exact channel by which a higher target can raise the reported number and lower revenue.
- Pull the evidence at consultant-month grain: plot realisation and the write-off share, written_off_hours over billable hours, against utilisation decile. If the current top decile already shows lower realisation, the proposed target moves a large share of the staff into that regime.
- Stratify before concluding. Fixed_fee teams can show high utilisation and high realisation for reasons that have nothing to do with the proposal, so run the comparison within pricing_model and report the mix.
- Propose the pair rather than the veto: utilisation published with realisation and write-off rate as standing guardrails, with the threshold at which the combination is net positive stated in advance. Then name your concession condition: if the top utilisation decile shows no realisation penalty and bench hours are the binding constraint, the target is right and you will say so.
Follow-up
- Utilisation and realisation are computed from overlapping hours. Does that make the relationship you found mechanical rather than behavioural?
- How many consultant-months would you need to detect a three-point realisation move, and does the firm have them?
- 01
Tell me about a time when you had to persuade a stakeholder to adopt your recommendation.
- 02
How do you prioritize your work when facing multiple deadlines?
- 03
Describe a challenging team dynamic you encountered and how you resolved it.
- 04
What motivates you to work as a Data Scientist?
- 05
How do you stay updated with the latest trends in data science?
- 06
How would you explain a complex machine learning model to a non-technical audience?
Is this an official 2nd Order Solutions interview guide?
No. It is PracHub's own preparation material for the Data Scientist role at 2nd Order Solutions. The rounds and questions reflect what candidates have reported, not a process the company has published, and they can change between teams and over time. Confirm the current format with your recruiter.
PracHub interview research ↗How difficult are the interviews for the Data Scientist position?
Candidates describe the technical interviews and the case studies as the hardest parts. The practical response is to rehearse out loud: a modelling case from target to metric, a statistics explanation, a SQL query with narration, and a case that ends in a recommendation.
PracHub interview research ↗How long does the process take?
Candidates report roughly three to five weeks across four rounds, and say they hear back within a few weeks of the final interview. This varies by team, so ask your recruiter for the schedule and plan your preparation to cover all four stages rather than only the first.
PracHub interview research ↗Which tools should I be ready to use?
The requirements candidates describe list Python or R, SQL, and a visualisation tool such as Tableau or Power BI, with statistics and machine learning as core skills. Cloud platforms such as AWS or Google Cloud, big-data tools such as Hadoop or Spark, and deep learning or NLP are listed as extras. Be able to write SQL and one of Python or R live; treat the extras as a way to talk about past projects.
PracHub Data Scientist practice ↗How should I structure a case study answer?
Candidates describe three moves: define the problem, explore the data to find the key variables, and generate insights as recommendations. In practice: restate the prompt as a decision, ask clarifying questions, name the quantity that would settle it, check data quality before analysis, state assumptions as you use them, and close with the action, supporting number and reversing result.
PracHub Data Scientist practice ↗Will there be coding and system design questions?
Candidates report coding and algorithm questions (a mean and median function, a decision tree from scratch, sorting complexity, a SQL ranking query) and data system design topics such as streaming, model deployment, analytical databases and data quality. These appear as question types that may apply depending on the team, so prepare small, correct code and a clear checklist-style design answer.
PracHub Data Scientist practice ↗Are remote or hybrid arrangements available?
Candidate reports do not confirm a specific policy; they say arrangements may vary by role. Ask your recruiter early, along with questions about the team, the data you would work with and how analyses reach decisions.
PracHub Data Scientist practice ↗Sources & methodology 3 sources ↗
Official role evidence, timestamped platform data and clearly labeled preparation advice.
- 01PracHub interview research ↗
PracHub editorial research into this company and role, maintained with this guide. Candidate-reported, not an employer publication.
platform · Accessed 2026-09-22 - 02PracHub Data Scientist practice ↗
Cross-company practice questions for this role.
platform · Accessed 2026-09-22 - 03PracHub interview preparation framework ↗
The framework the preparation plan follows.
platform · Accessed 2026-09-22