At PA Consulting, a Data Scientist occupies a unique and highly impactful position at the intersection of advanced technology, strategy, and client delivery. Unlike traditional technology firms where data scientists might work on a single product in isolation, PA Consulting operates as an innovation and transformation consultancy. This means you will deploy machine learning, predictive modeling, and statistical analysis to solve complex, real-world problems for diverse clients across industries such as healthcare, defense, energy, utilities, and the public sector.
The work you do as a Data Scientist directly influences critical strategic decisions, operational efficiencies, and innovative product developments for global organizations. You will be tasked with translating ambiguous, high-level business challenges into structured technical frameworks. Whether you are optimizing a supply chain, building predictive maintenance models for critical infrastructure, or leveraging natural language processing to streamline public services, your technical expertise will drive tangible, sustainable change.
This role is intellectually stimulating and highly collaborative, requiring you to work closely with software engineers, business designers, and industry specialists. To succeed, you must possess not only exceptional technical and analytical skills but also the consulting acumen to communicate complex data architectures and insights to non-technical stakeholders. It is a career path designed for those who want to see their code and models translated directly into real-world impact.
Application Submission
reportedBecause the format is not fixed, prepare the reasoning rather than the ritual. Nearly every version of this round draws on the same underlying material: a design you can defend, a metric you can define exactly, an analysis whose assumptions you can state out loud. Only the wrapper changes, whether that is a take-home, a live case, a deep dive on past work, or a rough estimate on a whiteboard. Answers rehearsed to fit one shape stall the moment the shape differs. Practise naming the assumption behind a number, then saying how much the conclusion moves if that assumption is wrong.
What to demonstrate
- Whether your justification for a method survives the question 'why not the simpler thing', including when the simpler thing would have worked
- Precision under pressure: what exactly counts as an active user, a conversion or a success, over what window, with what exclusions
- Whether you carry an argument through to a recommendation instead of stopping at a list of tradeoffs
How to prepare
- For each project you plan to mention, write the metric definition in one sentence: numerator, denominator, time window, exclusions. Say it out loud once, because vagueness shows up in speech before it shows up on paper.
- Rehearse the same project at three lengths: two minutes, ten minutes, and a deep dive on one technical decision. Cutting live is harder than it sounds.
- For your headline result, write down what would have had to be true for it to be wrong, and how you ruled that out.
Online Screening Assessments
reportedA handful of shapes account for most of what gets asked in this format: a ranking or deduplication inside groups, a running or rolling total, a period-over-period comparison, and a cohort tracked forward over time. Recognising the shape quickly is most of the speed here; deriving it from scratch while a clock runs is where the time goes. Know that a window function keeps every row while a GROUP BY collapses them, and know which one the question needs. If the exercise is in Python instead of SQL, the same shapes arrive as groupby with transform, shift and merge, and the same grain mistakes are available.
What to demonstrate
- Whether you reach the right construct without a detour, such as ROW_NUMBER over a partition to deduplicate instead of a self-join against a MAX subquery
- Whether you know what your window frame actually is, since adding ORDER BY inside OVER changes the default frame and silently changes a running total
- Whether the thing runs. A near-miss that throws an error scores below a plainer query that returns the right rows.
How to prepare
- Write each of the four shapes once from memory against a small schema and keep the working version somewhere you will reread it: dedupe with ROW_NUMBER, a running total, a month-over-month change with LAG, and a retention table
- Compute one running total twice on data with tied timestamps, once on the default frame and once with ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, and look at where the two disagree
- If Python is on the table, rebuild the dedupe and the running total with groupby and cumsum, then assert the two implementations return identical rows
Recruiter Conversation
reportedData Scientist covers at least four different jobs: experimentation, product analytics, causal work on observational data, and applied modelling that ships into a system. A screening call is the cheapest place to find out which of them is being hired for, and doing that diagnosis openly reads as senior rather than fussy. Ask what the last few pieces of work on the team actually were, and roughly how a week splits between querying, modelling and stakeholder time. Then say which parts of that you have done and which you have not. Claiming the whole range is the fastest way to be caught one round later.
What to demonstrate
- Whether you can distinguish the flavours of the role and locate your own experience inside one of them honestly
- Whether you name what you have not done instead of stretching to cover every line of the posting
- Whether your hard constraints (notice period, location, work authorisation, level) surface now rather than at offer stage
How to prepare
- Map the last two years of your time into rough percentages across query writing, experiment design, modelling and stakeholder work, so a question about scope has a real answer
- Mark every responsibility in the posting as done, adjacent or new, and prepare one sentence for each adjacent item naming the closest thing you have actually built
- Decide which logistics are non-negotiable before the call so you can state them in one sentence rather than negotiating live
Assessment Centre
reportedMuch of what gets scored here happens out loud while you type. Nobody can see your reasoning inside a half-written query, so five silent minutes read as being stuck even when they are not. State the plan in plain language first: which tables, what grain you are aggregating to, and the one filter that defines the population. Then write it. The narration doubles as insurance, because a wrong plan gets caught early and cheaply while a wrong query gets caught at the end with no time left to redo it. A timed statistics section, where one exists, is a separate test with its own clock.
What to demonstrate
- Whether the query you write matches the plan you just described
- What you do with a hint, meaning whether the correction gets absorbed or the first approach gets defended
- Whether you can debug your own wrong output by reading the result set and naming which part of the query produced the anomaly
How to prepare
- Solve three problems while screen-sharing into a recording, then watch it back and mark every stretch longer than thirty seconds where you said nothing
- Practise compressing the plan into one sentence before typing, then check afterwards whether the finished query actually matched it
- Time yourself on statistics questions that carry a business reading, such as what a confidence interval does and does not claim, rather than re-reading notes without a clock
PracHub editorial advice for the preparation topics above.
Treating accounts as independent observations
Revenue is concentrated: a small number of client_ids typically carries a large share of fees, and engagements within one account share a partner, a rate card and a delivery team. Ordinary standard errors computed over engagements therefore understate uncertainty badly. Cluster at client_id, and with fewer than roughly 40 clusters use a wild cluster bootstrap or a CR2 correction, because cluster-robust standard errors are downward-biased in that regime and will manufacture significance that a replication will not reproduce.
Trending utilisation or revenue on work_date without accounting for timesheet backfill
Time entries are created days to weeks after the work happens, and the backfill tail often runs two to six weeks. A dashboard keyed on work_date therefore shows the most recent weeks as a decline that reverses on every refresh. The fix is either to hold the reporting window back past the observed backfill tail (measure the tail with the timesheet submission lag metric rather than guessing) or to report an as-of-entered_at snapshot so the series is internally consistent, and to state which one you used.
Writing SQL without stating NULL and tie-breaking behaviour
Before calling a query finished, say what it does with NULLs, ties and empty groups. NOT IN against a subquery containing a single NULL returns no rows at all, and RANK, DENSE_RANK and ROW_NUMBER differ precisely on ties, so name which one the question requires.
Reporting a p-value with no effect size or interval
Give the estimated difference with a confidence interval in the units the business cares about, then say whether that whole interval is worth acting on. A p-value only addresses whether you can rule out exactly zero; it says nothing about magnitude.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Can you explain the difference between bagging and boosting, and when …
Can you explain the difference between bagging and boosting, and when you would choose one over the other?
Approach
- Set a baseline first, so any model has something honest to beat.
- Frame the prediction: the label, the moment of prediction, and the action it triggers.
- Say how the offline result would be validated online before it is trusted.
Follow-up
- How would you choose the decision threshold, and who owns that choice?
- What would you monitor after launch to know the model is still valid?
Describe a situation where a project or model did not perform as expec…
Describe a situation where a project or model did not perform as expected. What did you learn, and how did you pivot?
Approach
- Pick an evaluation metric that matches the cost of each error type, not a default.
- Check what information would not exist at prediction time, and exclude it.
- Frame the prediction: the label, the moment of prediction, and the action it triggers.
Follow-up
- How would you choose the decision threshold, and who owns that choice?
- Where could label leakage enter this setup?
Build a dense consultant-week hours spine with zero weeks
You are given time_entries (time_entry_id, consultant_id, engagement_id, charge_code, work_date as datetime64, hours, is_billable, status) and a list of consultant_ids in scope plus a start and end date. Produce a DataFrame with exactly one row per consultant per Monday-anchored week in that range, with columns consultant_id, week_start, billable_hours, total_hours. Weeks in which a consultant logged nothing must appear as zeros rather than be absent. Count only rows with status == 'approved'. Do not loop over consultants and do not use resample.
Approach
- Anchor weeks arithmetically: week_start = work_date - pd.to_timedelta(work_date.dt.weekday, unit='D'). Avoid dt.isocalendar().week, whose numbers restart each January and do not sort across a year boundary.
- Construct the spine from the inputs, not from the data: pd.date_range(start, end, freq='W-MON') crossed with the in-scope consultant_ids via pd.MultiIndex.from_product, so its size is fixed before any aggregation runs.
- Aggregate approved entries once with a single groupby on [consultant_id, week_start], producing total hours and billable hours (hours.where(is_billable, 0).sum()) in the same pass.
- Left-merge the aggregate onto the spine, fillna(0.0) on both hour columns, and keep float dtypes so later ratios do not integer-divide.
- Assert the shape before returning: len(out) == n_consultants * n_weeks, and out.total_hours.sum() equals the sum of hours over the filtered input inside the window.
Worked solution 20 min
- Filter to status == 'approved' and to work_date within [start, end], then derive week_start by subtracting the weekday offset.
- Build weeks = pd.date_range(start_monday, end, freq='W-MON') and spine = pd.MultiIndex.from_product([consultant_ids, weeks], names=['consultant_id','week_start']).to_frame(index=False).
- agg = filtered.assign(billable_hours=filtered.hours.where(filtered.is_billable, 0.0)).groupby(['consultant_id','week_start'], as_index=False)[['hours','billable_hours']].sum().
- out = spine.merge(agg, how='left', on=['consultant_id','week_start']).fillna({'hours':0.0,'billable_hours':0.0}).rename(columns={'hours':'total_hours'}).
- Sort by consultant_id then week_start and run the two assertions on row count and hour conservation.
Follow-up
- Utilisation gets computed on this spine. What breaks for a consultant hired mid-window or terminated mid-window, and where would you fix it?
- How would you extend this to consultant x engagement x week without the spine exploding to a row count nobody can hold in memory?
Deduplicate to the latest issued invoice line per engagement
fct_invoice_line holds invoice_line_id, invoice_id, engagement_id, line_type, period_end_date, amount_usd, issued_at and status; draft lines have issued_at NULL. Return exactly one row per engagement_id, its most recently issued line, with invoice_line_id, line_type, amount_usd and issued_at. Two lines on the same engagement can share an issued_at value to the second, so the result must be identical on every run against unchanged data. Write it with a window function, then say in one sentence when DISTINCT ON would be the better choice.
Approach
- Filter to issued lines (issued_at IS NOT NULL, status <> 'draft') before ranking. Ranking first and filtering afterwards can leave an engagement whose top-ranked row was a draft with no row at all in the output.
- Rank with ROW_NUMBER() OVER (PARTITION BY engagement_id ORDER BY issued_at DESC, invoice_line_id DESC). The surrogate key as the final ORDER BY term is what makes ties resolve the same way on every execution; without it the planner is free to return either tied row.
- Wrap the ranked query in a CTE or subquery and filter rn = 1, since a window function cannot appear in the WHERE clause of the query that computes it.
- Name why RANK() is wrong here: on tied issued_at it assigns 1 to both rows, so the result carries two rows for one engagement and any downstream SUM double counts.
- Compare against DISTINCT ON (engagement_id) ... ORDER BY engagement_id, issued_at DESC, invoice_line_id DESC: same answer, one sort, usually cheaper, but the window form generalises the moment you also want rn <= 3 or a second ranking in the same pass.
Follow-up
- Now return the latest line per engagement per line_type. What changes in the PARTITION BY, and what does that do to the row count?
- Return the latest and second-latest line together. Which of the two constructs survives that requirement?
- issued_at is TIMESTAMPTZ and finance reports on a single local calendar. Where can 'latest' flip between the two conventions?
Find signed engagements with no approved billable hour
fct_engagement holds engagement_id, start_date and status. fct_time_entry holds time_entry_id, consultant_id, engagement_id, charge_code, work_date, hours, is_billable and status, and engagement_id is NULL on bench, leave, training and internal rows. Return engagements with start_date in the trailing quarter and status IN ('active','closed_delivered','closed_early') that have no approved billable time entry with work_date within 45 days of start_date, giving engagement_id, start_date and days elapsed. Then explain why NOT IN over a subquery selecting fct_time_entry.engagement_id is the wrong instrument here.
Approach
- Express the exclusion as NOT EXISTS with a correlated predicate covering all four conditions at once: te.engagement_id = e.engagement_id AND te.is_billable AND te.status = 'approved' AND te.work_date < e.start_date + INTERVAL '45 days'. NOT IN can only carry a single column, so a multi-condition anti-join forces a contorted subquery even before the NULL problem.
- State the NULL semantics precisely: NOT IN (SELECT engagement_id FROM fct_time_entry) evaluates to NULL rather than TRUE for every candidate as soon as one NULL is present in the list, because x <> NULL is unknown. The WHERE clause keeps only TRUE, so the query returns zero rows and reads as a clean bill of health. This table guarantees NULLs, since bench and leave rows carry no engagement.
- Note the equivalent LEFT JOIN ... WHERE te.engagement_id IS NULL form. It is correct, but it materialises a join only to discard most of it; NOT EXISTS states the intent and most planners execute both as the same anti-join.
- Guard the window against truncation: an engagement that started 10 days ago cannot yet have failed a 45-day test, so require start_date <= current_date - 45 or report the too-early set separately rather than counting them as failures.
- Decide on the late-timesheet risk explicitly. A missing entry may mean unstaffed work or an unsubmitted timesheet, so either hold the cutoff back past the measured submission lag or label the recent tail as provisional.
Worked solution 20 min
- Count engagements matching the status and start_date predicates; this is the denominator.
- Write the NOT EXISTS version and record its row count.
- Write the NOT IN version on the same data and observe zero rows, then confirm with SELECT COUNT(*) FROM fct_time_entry WHERE engagement_id IS NULL that NULLs are present.
- Cross-check by counting engagements that DO have a qualifying entry and verifying the two counts sum to the denominator.
- Open one engagement from the result and look at its raw time entries to see whether the cause is no staffing or unapproved timesheets.
Follow-up
- Turn this into a time-to-first-billable-hour distribution. What do you do with engagements that never recorded one?
- Should client_pursuit hours count as the engagement being staffed, and how does that choice change the list?
- How would you prove the empty result from the NOT IN version is a bug rather than good news?
A major healthcare provider wants to reduce patient wait times using d…
A major healthcare provider wants to reduce patient wait times using data. How would you structure this project, and what data sources would you look for?
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
- How would you detect that the metric is being gamed rather than genuinely improving?
- What would you do if the primary metric and the guardrail moved in opposite directions?
How would you design a predictive maintenance framework for a manufact…
How would you design a predictive maintenance framework for a manufacturing client with limited historical sensor data?
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.
- State what result would change your recommendation, so the answer is falsifiable.
Follow-up
- What would you do if the primary metric and the guardrail moved in opposite directions?
- Which segment would you cut first, and what would that rule out?
How would you measure the business impact and return on investment (RO…
How would you measure the business impact and return on investment (ROI) of a newly deployed recommendation engine for a retail client?
Approach
- Fix the population and the time window before naming any metric.
- Restate the decision this analysis has to support, and who acts on the answer.
- 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 do you approach working in a multidisciplinary team where members …
How do you approach working in a multidisciplinary team where members have different priorities and backgrounds?
Approach
- State what result would change your recommendation, so the answer is falsifiable.
- 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
- Which segment would you cut first, and what would that rule out?
- How would you detect that the metric is being gamed rather than genuinely improving?
Size a rate-card pilot when accounts are the cluster
The firm wants to pilot a revised rate card. Assignment happens at the client account: one rate card per account, every engagement on it inherits that card. The outcome is realisation rate per engagement, fees billed over the standard-rate value of approved billable hours. You have 120 eligible accounts averaging three engagements each inside the pilot window, a per-engagement standard deviation of 0.12, and an intraclass correlation of 0.35 within account. Leadership will change the card only if realisation moves by at least 2 percentage points. Two-sided alpha 0.05, 80% power. Say whether this pilot can answer the question.
Approach
- Write the minimum detectable effect for a two-sample difference in means with equal allocation: MDE = (z_0.975 + z_0.80) * sigma * sqrt(4/N), coefficient 2.802, and be explicit that N counts engagements while randomisation happens on accounts.
- Convert engagements into independent information with the design effect DEFF = 1 + (m - 1) * rho. At m = 3 and rho = 0.35 that is 1.70, so 360 engagements carry the information of roughly 212.
- Compute the MDE on the effective sample, compare it to the 2-point decision threshold, and express the shortfall as a sample-size ratio rather than a vague 'underpowered'.
- Test whether a longer window rescues the design. Effective observations per cluster are capped at 1/rho, so total effective sample asymptotes at 120/0.35 = 343 no matter how long the pilot runs. Duration cannot fix an ICC problem; only more clusters can.
- Price the real options: more accounts, variance reduction from a pre-period covariate, a larger accepted effect size, or a design that uses within-account variation instead of between-account randomisation.
Worked solution 20 min
- DEFF = 1 + (3 - 1) * 0.35 = 1.70; effective n = 360 / 1.70 = 211.8.
- MDE constant = z_0.975 + z_0.80 = 1.960 + 0.8416 = 2.802.
- MDE = 2.802 * 0.12 * sqrt(4 / 211.8) = 2.802 * 0.12 * 0.1374 = 0.046.
- Invert for the 2-point target: required effective n = 4 * (2.802 * 0.12 / 0.02)^2 = 1131, so accounts needed = 1131 * 1.70 / 3 = 641.
- Take m to infinity for the duration ceiling: effective n approaches 120 / 0.35 = 343, giving an MDE floor of 2.802 * 0.12 * sqrt(4/343) = 0.036.
Follow-up
- Revenue is concentrated in a handful of accounts. How does a value-weighted estimate change the power calculation, and which estimand does leadership actually want?
- The ICC of 0.35 came from last year's data on the same accounts. What would make that estimate optimistic, and how would you stress it?
- What breaks if you randomise at the engagement instead of the account?
Fees per billable head fell nine percent; rank the causes
Recognised fees per billable head fell about 9% quarter over quarter and leadership wants a ranked cause by Friday. You have fct_time_entry, fct_invoice_line, fct_engagement and dim_consultant, plus a workday and regional holiday calendar. Decompose the move into available hours per head, billable utilisation and realised dollars per billable hour, separate calendar effects from behaviour, split within-segment change from mix, and deliver a ranked attribution with uncertainty. Name the one further cut you would run if the leading term is ambiguous.
Approach
- Write the identity before computing anything: fees per head = (available hours per head) x (billable utilisation) x (realised dollars per billable hour), where the last term is recognised fees divided by approved billable hours. Verify the product reproduces the reported 9% exactly; if it does not, the scope of the three inputs disagrees and nothing downstream is trustworthy.
- Decompose in logs: d ln(fees per head) = d ln(available per head) + d ln(utilisation) + d ln(realised rate). The log form is exactly additive for a product, so contributions sum to the total without an interaction residual and cannot attribute more than the whole move.
- Strip the calendar first, because it is the term nobody can act on: available hours per head moves with scheduled workdays, regional public holidays, leave and any change in fte_fraction mix. Quantify how many of the nine points are calendar and quote the remainder as the behavioural move.
- Split each surviving term by practice_area, level, region and pricing_model, and within each split separate within-segment change from mix using the weighted three-term decomposition, since a shift toward lower-rate levels reads as a rate decline that no individual rate produced.
- Attach uncertainty at the unit that generates it: anything fee-side clusters at client_id because engagements in one account share a partner, a rate card and a team. With fewer than roughly forty clusters use a wild cluster bootstrap or a CR2 correction, since cluster-robust standard errors are downward-biased in that regime.
- If realised rate leads and is ambiguous, the disambiguating cut is discount versus write-off versus fixed-fee overrun: compare invoiced fees to the standard-rate value of hours worked, and read written_off_hours and scope overrun by pricing_model.
Follow-up
- Two of the nine points are calendar. How do you say that to an executive without sounding like you are explaining the number away?
- Utilisation is up and realised rate is down. What single operational behaviour produces both, and how would you confirm it?
- What would you need to see to claim this is a demand problem rather than a delivery or pricing one?
For someone who has spent the last year in notebooks, dashboards or modelling work and has not written raw SQL under time pressure. The first four days rebuild query fluency against a fixture you control and can verify by hand; the last three attach that fluency to the rest of the loop.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Build a fixture you can check answers against
- Create a local Postgres or SQLite database with four tables (users, sessions, events, orders) holding roughly 200 rows you generated yourself, so you know the contents well enough to predict every result.
- Deliberately seed the cases that break queries: a user with no sessions, a session with no events, two orders sharing a timestamp, a NULL in one join key, and one duplicated user row.
- Before writing any SQL, hand-compute five answers on paper (how many users placed at least one order, median orders per ordering user, and three others) and save them as the ground truth for the week.
Deliverable: A one-command seed script plus a text file of five hand-computed answers to grade every later query against.
Practice prompt ↗Practice prompt ↗Worked solution ↗02Joins, filters and NULL semantics
- Answer "which users have no orders" three ways (LEFT JOIN with IS NULL, NOT EXISTS, NOT IN) and confirm that the NOT IN version returns zero rows once the subquery contains a NULL, because the comparison is never TRUE.
- Reproduce the LEFT JOIN that silently collapses to an inner join by putting a right-table predicate in WHERE, then fix it by moving the predicate into the ON clause, and record both row counts.
- Create a fan-out bug on purpose by joining orders to order_items and summing the order total, then correct it with a pre-aggregated subquery and explain in one line which table changed the grain.
Deliverable: One annotated .sql file holding the three join traps, each with the wrong result and the corrected result side by side.
Practice prompt ↗Practice prompt ↗03Window functions and frames
- Write three window queries against the fixture: a running order total per user, the rank of each order within its user by value, and the day gap to that user's previous order, then check each against the day-one ground truth.
- Run ROW_NUMBER, RANK and DENSE_RANK over a column containing ties, print all three side by side, and write one sentence on when each is the correct choice.
- Switch one query from the default frame (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, which is what you get when ORDER BY is present and no frame is written) to ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, and explain why the output differs only when the ORDER BY column has duplicates.
Deliverable: Three verified window queries plus a short note explaining the RANGE versus ROWS difference in your own words.
Practice prompt ↗Practice prompt ↗04The four analytical query patterns
- Write a monthly retention grid: first order month per user, then months-since-first as the column, and verify that month zero equals the cohort size exactly.
- Sessionize the events table under a 30-minute inactivity rule using LAG plus a cumulative sum over a new-session flag.
- Build a four-step funnel that counts distinct users rather than events at each step, and state the rule you applied to a user who reaches step three without ever logging step two.
Deliverable: One file with the retention, sessionization and funnel patterns, each carrying a one-line note on the assumption it bakes in.
Practice prompt ↗Practice prompt ↗Worked solution ↗05Write SQL the way you will have to write it live
- Set a 12-minute timer and solve three medium prompts in a plain editor with no execution and no autocomplete, then run them and tally syntax errors separately from logic errors.
- Narrate one solution aloud while writing it, stating the grain of each intermediate result (one row per user, one row per user-day) before you type its body.
- Rewrite your slowest solution as a CTE chain where every CTE name states its grain, and time yourself re-solving it from blank.
Deliverable: A recording of one narrated solution plus an error tally that separates syntax from logic.
Practice prompt ↗Practice prompt ↗06One day for everything that is not SQL
- Write the preconditions of the two-sample t-test from memory, then check them: independent observations, and a difference in means whose sampling distribution is approximately normal, which at large sample sizes follows from the central limit theorem rather than from normality of the raw values.
- Write the difference between an odds ratio from logistic regression and a relative risk, and state the condition under which the two are close (low outcome prevalence).
- Prepare a 90-second answer to "how would you know this model is any good" that names the metric, the baseline you would beat, and the cost of the errors you care about.
Deliverable: One page of notes covering test preconditions, the odds-ratio caveat and the model-quality answer.
Practice prompt ↗Practice prompt ↗07Full loop rehearsal
- Run a 45-minute mock with someone willing to interrupt: 20 minutes of SQL, 15 minutes defining a metric, 10 minutes on a past project.
- Re-solve from blank the two queries you were slowest on this week and compare the times against day five.
- Write a five-line answer to "walk me through a project" that puts a number in the first sentence and names the decision the work changed.
Deliverable: Mock feedback notes plus a timed project narrative you can deliver without reading it.
Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
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.
How do you handle a situation where a client is skeptical of your data…
How do you handle a situation where a client is skeptical of your data-driven recommendations?
Approach
- State the situation in two sentences and spend the rest on your reasoning.
- Name the disagreement or constraint, and how you resolved it with evidence.
- Close with what you would do differently, concretely.
Follow-up
- What did you decide not to do, and why?
- What would you do differently if you ran that project again?
How do you handle missing data or highly imbalanced datasets when trai…
How do you handle missing data or highly imbalanced datasets when training a predictive model?
Approach
- Pick a story where you drove the decision, not one where you observed it.
- Close with what you would do differently, concretely.
- State the situation in two sentences and spend the rest on your reasoning.
Follow-up
- What did you decide not to do, and why?
- What would you do differently if you ran that project again?
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?
- 01
How do you handle a situation where a client is skeptical of your data-driven recommendations?
- 02
How do you handle missing data or highly imbalanced datasets when training a predictive model?
- 03
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.
Is this an official PA Consulting interview guide?
No. It is PracHub's own research and practice material for the Data Scientist role at PA Consulting. Rounds and questions reflect what candidates have reported, not a process PA Consulting has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗How difficult is the Data Scientist interview process at PA Consulting?
The overall difficulty is rated as average to challenging. While the technical questions are grounded in fundamental machine learning and coding principles, the complexity lies in the multi-stage Assessment Centre, which tests your ability to present, collaborate, and solve case studies under strict time limits.
PracHub interview research ↗What should I expect during the 5-minute presentation?
You will be given a technical scenario or dataset to analyze during the assessment day. You must synthesize this information into a 5-minute presentation. Focus on delivering a clear narrative, defining the business problem, explaining your technical approach, and outlining the business impact.
PracHub interview research ↗How can I stand out in the group or pair exercise?
Successful candidates demonstrate collaborative leadership. Focus on active listening, encourage quieter team members to speak, keep track of the time, and help structure the group’s thoughts. Avoid dominating the conversation or dismissing others' ideas.
PracHub interview research ↗What is the remote and hybrid work policy for Data Scientists?
PA Consulting operates a hybrid model. While you will have flexibility to work from home, you will also spend time in your local office (such as London) and traveling to client sites as required by the projects you are supporting.
PracHub interview research ↗Sources & methodology 3 sources ↗
No official company page is cited. Rounds and questions come from candidate reports and PracHub editorial material; each source shows the date it was read.
- 01PracHub interview research ↗
PracHub editorial research into this company and role, maintained with this guide. Candidate-reported, not an employer publication.
PracHub page · Accessed 2026-09-22 - 02PracHub Data Scientist practice ↗
Cross-company practice questions for this role.
PracHub page · Accessed 2026-09-22 - 03PracHub interview preparation framework ↗
The framework the preparation plan follows.
PracHub page · Accessed 2026-09-22