At People Tech Group, a Data Scientist plays a pivotal role in bridging the gap between raw enterprise data and intelligent, automated decision-making. As a premier IT consulting and software services provider, the company relies heavily on its data science talent to design, build, and deploy scalable machine learning solutions for a diverse portfolio of global clients. You will not just be building models in isolation; you will be architecting end-to-end pipelines that directly impact client digital transformation initiatives and optimize enterprise-level business workflows.
The role is highly dynamic and sits at the intersection of classical predictive modeling and modern generative AI. Because People Tech Group services multiple industries, your work could span from optimizing supply chain logistics to building advanced natural language processing tools that redefine customer engagement. The team operates in an agile, collaborative environment where you will work alongside cloud architects, software engineers, and business stakeholders to translate complex technical concepts into tangible business value.
To succeed as a Data Scientist here, you must possess a blend of strong mathematical fundamentals, hands-on coding capabilities, and a keen interest in emerging technologies like Large Language Models (LLMs). The company values self-starters who can take ownership of a project from data ingestion to production deployment, making this an exceptionally rewarding opportunity for engineering-minded scientists who thrive on variety and real-world impact.
Initial Screening
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
Technical Evaluation
reportedBefore anything else, this round is a reading test. You are given a small schema and a question phrased in business language, and most of the difficulty sits in the gap between them. Who counts as an active user, does a refunded order still count as an order, is that date column an event time or a load time. Weak answers start typing immediately and compute something precise about the wrong population. Strong ones pin the definition in one sentence, name the column that encodes it, then write the query. On a timed assessment with nobody to tell, write the definition in a comment anyway.
What to demonstrate
- Whether an ambiguous term becomes a specific column and filter before any computation happens
- Whether you read the schema for keys and cardinality rather than only for column names
- Whether the result answers the question at the grain it was asked at, per user or per session or per day
How to prepare
- Take three metrics you already use and write down the exact filter and exact grain behind each, then practise stating one of them in a single sentence out loud
- On a schema you have never seen, spend the first minute writing what one row of each table means and which key it is unique on, then predict which joins can duplicate rows
- Rehearse a version where the definition changes halfway through, and edit the query you have instead of starting over
Leadership Alignment
reportedAn extra round usually exists because something is still open after the standard loop: a skill the earlier interviews did not sample, a level decision, or two interviewers who disagreed. It is rarely a rerun of what you already did well. Ask the recruiter who you are meeting, what function they sit in, and how long the session runs. That is an ordinary scheduling question, and the answer changes what you should prepare. What separates a strong candidate here is treating the round as a fresh evaluation with its own bar, rather than assuming earlier performance carries you through or sinks you.
What to demonstrate
- Whether you can answer well on ground the earlier rounds did not cover, without leaning on what you already said to someone else
- Consistency of the facts in your stories: the same sample size, timeframe, team size and scope of your own role as in earlier conversations
- How you handle an unfamiliar format live, including whether you ask what kind of answer is wanted before producing one
How to prepare
- Ask the recruiter for the interviewer's function, the length, and whether to expect a coding surface, a discussion, or a presentation. Preparing for a 30 minute conversation with a partner team is not the same work as preparing for a 60 minute technical block.
- Write out what each earlier round actually covered, then list the two or three areas nobody probed. That gap is the most likely subject of the extra round.
- Re-read the numbers in the project stories you have already told, so a second telling does not quietly contradict the first.
Comprehensive Technical Panel
reportedWhere a loop ends with a senior leader, that conversation is rarely another skills test. The technical signal already exists by then, so the questions tend to open up: what you would look at first, where a metric you have heard about could mislead, what you would push back on. The decision being made is scope, which in practice means level and how much you would be trusted to own unsupervised. Treating it as a formality is the usual mistake. An open question late in the day is still being scored, and a vague answer reads as someone who has not run anything themselves.
What to demonstrate
- Whether your view of the business has anything specific behind it, given that you are working only from what is public and are expected to say so
- Whether the scope of work you describe owning matches the scope of the role, instead of sitting a level below it
- Whether you can disagree with something concrete and stay useful about it, rather than agreeing with everything said in the room
- Whether your questions are ones only this person could answer, as opposed to ones the recruiter already covered
How to prepare
- Build one view you could defend for two minutes using only public information: what the funnel probably looks like, which metric likely drives decisions, and where that metric could mislead. Being wrong for a stated reason survives this round; having no view does not
- Write down the largest piece of work you have owned from question to decision, who else touched it, and what you decided alone, then check that it reads at the level you are interviewing for
- Prepare one thing you would want changed if you joined and phrase it as a question rather than a verdict, so it opens a conversation instead of closing one
PracHub editorial advice for the preparation topics above.
Randomising an experiment at the user level when users share an account
Two problems fire at once. Colleagues in one workspace see each other's work and talk to each other, so a treated user changes the behaviour of a control user in the same account, which violates the no-interference assumption and biases the estimate toward zero. Separately, outcomes within an account are strongly correlated, so the effective sample size is roughly n / (1 + (m - 1) * rho) for m users per account and intra-class correlation rho, not n. With rho around 0.3 and twenty users per account that is a design effect near 6.7, meaning a user-level confidence interval is about two and a half times narrower than it should be and results cross significance thresholds on noise alone. Randomise the account and cluster the standard errors.
Computing monthly churn against the entire customer base when contracts are annual
An annual contract has no opportunity to churn except at its renewal date, so an account that is eleven months from renewal is in the denominator while being incapable of appearing in the numerator. The resulting rate is smaller than the real one by roughly the ratio of the base to the renewal-eligible base, and it oscillates with the seasonality of when deals were originally signed rather than with anything about the customers. The corresponding trap on the other side is counting a churn on the date the record was updated rather than on term_end_date, which shifts losses into whichever month the operations team did its paperwork.
Reading a dozen metrics with no multiplicity control
Nominate one primary metric before launch and treat the rest as guardrails or exploratory, with Bonferroni or Benjamini-Hochberg applied when you intend to make claims from them. Twenty independent tests at 0.05 under the null produce at least one false positive about 64 percent of the time.
Comparing periods without accounting for seasonality or day-of-week
Compare whole weeks against whole weeks and check whether the same swing appeared in prior cycles or prior years before attributing it to anything you changed. Weekday and weekend populations often differ enough that a Tuesday-to-Saturday comparison is meaningless.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
How do you address the issue of multicollinearity in linear regression…
How do you address the issue of multicollinearity in linear regression models?
Approach
- Frame the prediction: the label, the moment of prediction, and the action it triggers.
- Pick an evaluation metric that matches the cost of each error type, not a default.
- Say how the offline result would be validated online before it is trusted.
Follow-up
- Where could label leakage enter this setup?
- What would you monitor after launch to know the model is still valid?
What is Retrieval-Augmented Generation (RAG), and how does it improve …
What is Retrieval-Augmented Generation (RAG), and how does it improve the output of a Large Language Model?
Approach
- Say how the offline result would be validated online before it is trusted.
- Set a baseline first, so any model has something honest to beat.
- Check what information would not exist at prediction time, and exclude it.
Follow-up
- What would you monitor after launch to know the model is still valid?
- How would you choose the decision threshold, and who owns that choice?
Write a script to build a baseline classification model using Scikit-L…
Write a script to build a baseline classification model using Scikit-Learn and output a comprehensive classification report.
Approach
- Frame the prediction: the label, the moment of prediction, and the action it triggers.
- Pick an evaluation metric that matches the cost of each error type, not a default.
- Set a baseline first, so any model has something honest to beat.
Follow-up
- What would you monitor after launch to know the model is still valid?
- Where could label leakage enter this setup?
Bootstrap a confidence interval for net revenue retention
You have one row per account with arr_start_cents (ARR twelve months ago) and arr_end_cents (ARR today, zero if churned), covering the fixed cohort of accounts that had ARR twelve months ago. Net revenue retention is sum(arr_end_cents) / sum(arr_start_cents). Write a nonparametric bootstrap from scratch, without scipy.stats.bootstrap: resample accounts with replacement, recompute the ratio of sums on each resample, and return the point estimate with a 95% percentile interval from 10,000 resamples. Also report the interval you would get from the mean of per-account ratios, and explain the difference.
Approach
- Resample the account, because the account is the unit the estimand is defined over. One bootstrap draw is a vector of account indices and both numerator and denominator are recomputed from that same draw; resampling the two sides independently destroys the within-account correlation that makes a ratio estimator stable.
- Vectorise the draws: idx = rng.integers(0, n, size=(B, n)), then end[idx].sum(axis=1) / start[idx].sum(axis=1). A 10,000 by n index matrix is usually far cheaper than a Python loop; if the matrix is too large for memory, chunk over B rather than reverting to a loop.
- Take the interval from np.quantile(ratios, [0.025, 0.975]). The percentile interval differs from estimate +/- 1.96 * bootstrap SE whenever the resample distribution is skewed, which it will be here, and the skew is the thing you want represented.
- Compute the mean-of-ratios version on the same resamples, and state the exact relationship rather than guessing which of the two is larger. With r_i = arr_end_i / arr_start_i, the ratio of sums is the arr_start-weighted mean of exactly those r_i, so sum(end)/sum(start) - mean(r) = Cov(arr_start, r) / mean(arr_start) using the population covariance. The gap is positive when larger accounts retain and expand better than smaller ones, and negative when they do not; a cohort whose small accounts churn at a higher rate has positive covariance, which puts the mean of per-account ratios BELOW the ratio of sums. Requires arr_start_i > 0 for every account, which the fixed-cohort definition guarantees; r_i is floored at 0 and unbounded above, so a handful of 4x expansions among small accounts can flip the sign. Compute the covariance and report it instead of asserting a direction.
- Report the interval width beside the concentration of the cohort. If the largest account is 12% of starting ARR, a narrow interval is evidence that the resampling unit is wrong rather than evidence that the estimate is precise.
Worked solution 30 min
- start = df.arr_start_cents.to_numpy(float); end = df.arr_end_cents.to_numpy(float); n = len(start); point = end.sum() / start.sum()
- rng = np.random.default_rng(7); idx = rng.integers(0, n, size=(10_000, n)); ratios = end[idx].sum(1) / start[idx].sum(1)
- lo, hi = np.quantile(ratios, [0.025, 0.975]); return point, lo, hi
- per_acct = end / start; mean_point = per_acct.mean(); mean_boot = per_acct[idx].mean(1); compare np.quantile(mean_boot, [0.025, 0.975]) against (lo, hi), and report np.cov(start, per_acct, ddof=0)[0,1] / start.mean() as the quantity that accounts for the gap between the two centres.
Follow-up
- The cohort has 800 accounts and the largest is 12% of starting ARR. How much do you trust a percentile interval here?
- How would you extend this to an interval on the year-over-year change in NRR?
- Two accounts merged mid-window and one contract was co-termed into the other. How do you keep the cohort fixed?
Write a Python function to perform data preprocessing on a messy datas…
Write a Python function to perform data preprocessing on a messy dataset, handling missing values and encoding categorical variables.
Approach
- Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.
- Check whether any join is one-to-many before aggregating, or the sums inflate.
- Say which table is the grain you start from, and join outward from it.
Follow-up
- How would you verify this result without re-running the same query?
- What breaks if events arrive late or out of order?
How would you implement a custom cross-validation loop from scratch in…
How would you implement a custom cross-validation loop from scratch in Python?
Approach
- Say which table is the grain you start from, and join outward from it.
- Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.
- State the window function and its partition and ordering out loud before writing it.
Follow-up
- How does the query change if the join becomes one-to-many?
- What breaks if events arrive late or out of order?
Net revenue retention on a cohort frozen twelve months back
fct_subscription_period carries subscription_period_id, account_id, arr_cents, plan_code, term_start_date, term_end_date, booked_at, amendment_type, superseded_by_id (the subscription_period_id of the version that replaced this one, null on the live version of a lineage) and is_current. Compute net revenue retention for month M: the summed arr_cents at M for the set of accounts holding arr_cents > 0 at M-12, divided by that same set's arr_cents at M-12. An account can hold more than one live subscription, a churned account contributes zero rather than dropping out, and nothing signed after M-12 may enter either side. Return the ratio plus the expansion, contraction and churn components in cents.
Approach
- Write one reusable as-of ARR snapshot parameterised by a date: rows whose term brackets the date AND whose booked_at is at or before the date, then only the version of each lineage that is still live at that date, then sum arr_cents per account. The booked_at guard matters because an amendment signed in advance otherwise co-exists with the term it replaces and double counts the account.
- Collapse the lineage on superseded_by_id, not on any attribute of the contract. Keep a row when superseded_by_id IS NULL, or when the successor it points at was booked after the date. Ranking with ROW_NUMBER() OVER (PARTITION BY account_id, plan_code ...) instead is wrong in both directions: an amendment that moves the account from one plan_code to another puts the old and new versions in different partitions, so both are rank 1, both bracket the date, and the account's arr_cents is counted twice; and two genuinely concurrent subscriptions that happen to share a plan_code land in one partition, so one of them is deleted.
- Resolve the successor with a LEFT JOIN back to fct_subscription_period on subscription_period_id, and treat a missing successor as not superseded. An inner join would silently delete an account's ARR on a dangling pointer, which is a data-quality bug in the source, not a retention movement.
- Never use is_current for the M-12 side. is_current describes today; using it at the historical snapshot backdates the present contract onto last year's cohort and makes retention look like 100 percent by construction.
- Freeze the cohort from the M-12 snapshot where arr_cents > 0, then LEFT JOIN the M snapshot onto it and COALESCE the missing side to zero. An inner join deletes exactly the churned accounts, which is the single largest way this number gets overstated.
- Return a ratio of sums, not a mean of per-account ratios. The two are different estimands: contraction is floored at zero while expansion is unbounded, so the mean of ratios is both biased relative to the aggregate and far noisier on a skewed revenue base.
- Decompose per account on the delta: positive delta is expansion, negative delta with a non-zero M value is contraction, a zero M value is churn. The three components must reconcile to numerator minus denominator.
- Prove no leakage: any account whose first contract began after M-12 must be absent from both sides, and the cohort row count must be identical in the numerator and denominator.
Worked solution 45 min
- Write arr_asof(d) as a CTE or lateral: from fct_subscription_period s take rows with term_start_date <= d AND term_end_date >= d AND booked_at <= d, LEFT JOIN fct_subscription_period succ ON succ.subscription_period_id = s.superseded_by_id, keep the row when s.superseded_by_id IS NULL OR succ.subscription_period_id IS NULL OR succ.booked_at > d, then sum arr_cents per account_id across every surviving version.
- Sanity-check the lineage rule on one amended account before going further: at a date after the amendment, the account must contribute exactly one version per lineage even when the amendment changed plan_code, term dates or both.
- Materialise base = arr_asof(M-12) filtered to arr_cents > 0, and curr = arr_asof(M).
- LEFT JOIN curr onto base on account_id and COALESCE(curr.arr_cents, 0) AS arr_now.
- Compute nrr = sum(arr_now)::numeric / NULLIF(sum(base.arr_cents), 0), and the three components with SUM(...) FILTER on the sign of arr_now - base.arr_cents and on arr_now = 0.
- Reconcile: assert sum(arr_now) - sum(base.arr_cents) = expansion - contraction - churn, and assert the cohort account count is identical on both sides.
Follow-up
- Net revenue retention can rise while the business shrinks. Show one mechanism and name the guardrail that catches it.
- How do you handle an account that co-terms two subscriptions into one mid-window, so the subscription count changes but the money does not?
- Finance computes this from invoiced amounts and gets a different number. Which is right for which question?
How do you optimize memory usage when processing large datasets in Pan…
How do you optimize memory usage when processing large datasets in Pandas?
Approach
- State what result would change your recommendation, so the answer is falsifiable.
- Name one primary metric, then the guardrail that stops it being gamed.
- Fix the population and the time window before naming any metric.
Follow-up
- Which segment would you cut first, and what would that rule out?
- What would you do if the primary metric and the guardrail moved in opposite directions?
How do you evaluate the factual accuracy and mitigate hallucinations i…
How do you evaluate the factual accuracy and mitigate hallucinations in generative AI applications?
Approach
- Say what you would check first and why it is the highest-information step.
- State your assumptions explicitly before working the problem.
- Work from the decision backwards to the evidence you would need.
Follow-up
- How would you know your answer was wrong?
- What assumption would you test first?
Size an account-randomised test of a consumption feature
You have 2,800 non-internal paying accounts. The outcome is the monthly sum of billable_quantity for sku_code = 'compute_hours' from fct_usage_daily, with a mean of 640 and a standard deviation of 2,100 across accounts. Product wants to detect a 5% lift from a scheduling feature, randomised 50/50 at the account level, at 80% power and two-sided alpha 0.05. Give the minimum detectable effect the available sample actually supports, say whether the 5% target is reachable, and state what you would change in the design or the metric before agreeing to run it.
Approach
- Write the two-sample formula and plug it before discussing anything else: MDE = (z_0.975 + z_0.80) * sd * sqrt(1/n1 + 1/n2) = 2.80 * 2100 * sqrt(2/1400) = 222 compute-hours, which is 34.7% of the 640 mean. The driver is the coefficient of variation of 3.3, not the account count, so quoting a sample size without it is not a power calculation.
- Invert for the stated target. A 5% lift is 32 compute-hours, needing N = 4 * (2.80 * 2100 / 32)^2 = about 135,000 accounts, roughly 48 times the eligible population. Say the test is not powerable on this metric, and do not offer to run it longer: the account population is fixed, and extra weeks add repeated observations on the same clusters rather than new clusters.
- Attack the variance instead of the sample. Pre-register winsorisation at the 99th percentile of the pre-period distribution, or move the estimand to a bounded one such as the share of accounts exceeding a usage floor. State explicitly that this changes the estimand rather than cleaning the data, because a cap chosen after seeing the result encodes the answer.
- Add CUPED on the account's pre-period compute_hours. At a pre/post correlation of 0.80 the residual variance multiplier is 1 - 0.80^2 = 0.36, the standard error falls to 0.60 of its unadjusted value, and the MDE drops from 222 to 133 compute-hours (20.8% relative). That is still four times the requested 5%.
- Fix the randomisation unit and the balance in the same breath: randomise account_id because colleagues share workspaces, and stratify assignment on pre-period usage decile so that a handful of very large accounts cannot land disproportionately in one arm and dominate the difference in means.
- Close with an operating decision rather than a number. Run only if the team will act on a roughly 20% MDE after CUPED and winsorisation; otherwise re-specify the primary outcome as a bounded indicator and treat compute-hours as a secondary reported with intervals only.
Worked solution 25 min
- Compute the coefficient of variation, 2100 / 640 = 3.28, and check the top-decile share of total compute_hours before treating the mean as a summary of anything.
- Compute MDE = 2.80 * 2100 * sqrt(1/1400 + 1/1400) = 2.80 * 2100 * 0.0378 = 222 compute-hours, 34.7% relative.
- Invert to the required N for a 32-hour effect: 4 * (5883 / 32)^2 = about 135,000 accounts, 48x the population.
- Recompute under CUPED at rho = 0.80: variance multiplier 0.36, SE multiplier 0.60, MDE 133 compute-hours, 20.8% relative.
- Recompute on the binary variant at base rate 0.46 and write the recommendation as one decision with one operating point.
Follow-up
- The feature only applies to the 310 accounts on committed_consumption contracts. What is the MDE on that subset, and does it change the recommendation?
- Suppose the primary outcome becomes a binary indicator, account exceeded 100 compute-hours in the month, at a base rate of 0.46. What is the MDE now, and why did it improve so much?
- What would make you stop this test early, and how do you write that rule so it is not peeking?
Net revenue retention jumps sixteen points in one month
Trailing-twelve-month net revenue retention printed around 108 percent for months and now reads 124 percent, with no unusual deals closed. The query sums arr_cents from fct_subscription_period (account_id, arr_cents, term_start_date, term_end_date, amendment_type, superseded_by_id, is_current, booked_at) filtered on is_current = true at month M, across accounts holding arr_cents > 0 at month M-12. Find the defect, correct the number, and rewrite the definition so the next person cannot reintroduce it.
Approach
- Audit the grain before the arithmetic: count account_ids holding more than one row with is_current = true and superseded_by_id null. A versioned contract table that double counts one amendment batch inflates the numerator while leaving the denominator untouched.
- Replace is_current with an as-of selection on both dates, taking the version whose term_start_date and term_end_date bracket the reporting date and tie-breaking on latest booked_at. The numerator is read as of M and the denominator as of M-12; neither uses today's live version.
- Verify the cohort is frozen. The account set is fixed at M-12 and nothing acquired since may enter the numerator, so check that no join to a current-period table quietly re-admits new accounts.
- Confirm the estimand is a ratio of sums rather than a mean of per-account ratios. Contraction is floored at zero while expansion is unbounded, so the two constructions differ systematically and the second is far noisier.
- Reissue the definition with the failure modes written into it: exactly one row per account per date by construction, cohort frozen at M-12, churned accounts contributing zero rather than dropping out of the numerator.
Follow-up
- A churned account should contribute zero rather than disappear. What does the ratio do under each treatment, and which one is correct?
- How would you unit-test this metric so a future amendment batch with the same defect fails a check instead of reaching a board slide?
For a candidate whose interviews will centre on A/B testing, metric movement and causal claims. Design comes before arithmetic, arithmetic before analysis, and the week ends by rehearsing the readout rather than the derivation.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Design one test end to end on paper
- Take a single feature change and write the full design: randomization unit, the exact point of exposure, the primary metric with its grain, guardrails, allocation, planned duration, and the decision rule committed before any data exists.
- Write why the randomization unit must sit at or above the level where treatment can spill over, and give one case where user-level randomization is still contaminated (shared accounts or devices, or two participants in the same marketplace).
- State in advance what you will do if the primary metric is flat while a secondary metric is significant.
Deliverable: A one-page test design with a decision rule written before launch.
Practice prompt ↗Practice prompt ↗Worked solution ↗02Power arithmetic until it is automatic
- Compute required sample size per arm for a binary metric with the normal approximation, n is approximately 2 times (z for alpha/2 plus z for power) squared times p(1 minus p) divided by delta squared, for baselines of 2, 10 and 40 percent at a 5 percent relative lift, and note that for a fixed relative lift the requirement falls as the baseline rises because delta grows proportionally with p.
- Redo the calculation for a continuous metric using variance in place of p(1 minus p), and show why a heavy-tailed quantity such as revenue per user needs either far more traffic or a capped version with a stated cap.
- Convert one of the results into weeks given a weekly eligible traffic figure, then list the two honest ways to shorten it (accept a larger detectable effect, or reduce variance) and write why quietly lowering the power target is a decision to miss more real wins, not a speedup.
Deliverable: A small script or sheet that maps baseline, minimum detectable effect, alpha and power to sample size and weeks, cross-checked against a published calculator.
Practice prompt ↗Practice prompt ↗03Variance and the unit-of-analysis problem
- Take a ratio metric whose denominator is not the randomization unit (clicks per session, randomized by user) and compute the standard error twice, once naively at session level and once by the delta method or a user-level bootstrap, then record how much the naive version understates it.
- Implement CUPED on simulated data: choose a pre-period covariate X measured before assignment, estimate theta as Cov(Y, X) divided by Var(X), and analyse Y minus theta times (X minus its mean) in place of Y. Confirm the variance of the adjusted outcome equals the raw variance multiplied by one minus the squared correlation between Y and X, so a correlation of 0.45 removes about 20 percent of the variance and not 80.
- Now run that simulation a few hundred times and confirm the adjusted effect estimate is unbiased for the same effect rather than numerically identical to the raw one. Within any single run the two differ, sometimes by a large fraction of the true effect, because the two arms' pre-period covariate means never coincide exactly in a finite sample; they agree in expectation, which is the property that matters and the one to state out loud.
Deliverable: A notebook showing the adjusted estimator with a measurably smaller variance than the raw one, plus a repeated-simulation table showing the two estimators agreeing on average while differing run by run.
Practice prompt ↗Practice prompt ↗04Validity threats you can actually test for
- Run a sample ratio mismatch check as a chi-square goodness-of-fit test against the intended allocation, and write the three causes you would chase first (assignment logged before exposure, an arm-specific redirect or load failure, bot filtering applied asymmetrically).
- Simulate peeking: generate A/A data, test daily at alpha 0.05 across 14 looks, record the inflated false positive rate, then apply an alpha-spending boundary or commit to a fixed horizon and confirm the rate returns to nominal.
- Write how you would separate a novelty effect from a durable lift using the treatment effect plotted against days since first exposure, and what shape would change your recommendation.
Deliverable: One table showing the peeking false positive rate before and after correction, plus a written SRM triage list.
Practice prompt ↗Practice prompt ↗Worked solution ↗05When randomization is not available
- Write the identifying assumption for difference-in-differences (parallel trends in the absence of treatment), then plot pre-period trends for two candidate control groups and justify rejecting one of them.
- Design a switchback test for a change where user-level randomization would leak across participants, choosing a time-block length against the carryover you expect and saying how you would detect carryover in the data.
- List what an interrupted time series or a synthetic control buys you and the one thing neither can rule out: an unobserved shock that coincides with the launch.
Deliverable: A one-page memo recommending a single quasi-experimental design and naming its weakest assumption explicitly.
Practice prompt ↗Practice prompt ↗06The readout query
- Write the assignment-to-exposure join that returns exactly one row per unit per experiment, and handle units appearing in both arms by excluding and counting them rather than silently keeping one.
- Compute the per-arm metric, its variance and the relative lift with a confidence interval in SQL, then reproduce the identical numbers in a notebook as a cross-check.
- Add a segment breakdown and write the sentence that keeps it from being p-hacking: segments declared in advance, everything else reported as exploratory and corrected for multiplicity.
Deliverable: A single query that outputs the full readout table, matched to a notebook recomputation.
Practice prompt ↗Practice prompt ↗07Present it to someone who will not read the appendix
- Give a 10-minute readout of a real or simulated experiment in the order decision, number, uncertainty, caveat.
- Have your listener ask "can we ship it" in the case where the primary is flat and a guardrail moved, and answer with a recommendation rather than a request for more data.
- Rewrite your opening line so the recommendation lands before any methodology.
Deliverable: A one-page readout whose first line is the recommendation.
Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
Half of this section is about translation. Be ready to describe how you explained a result to someone who did not want the method, only the implication, and what you did when the simplified version started being repeated in a way that overstated it. Correcting your own simplification is a strong beat.
Walk me through a complex data science project from your resume, focus…
Walk me through a complex data science project from your resume, focusing on your specific contributions and the business outcomes.
Approach
- State the situation in two sentences and spend the rest on your reasoning.
- Pick a story where you drove the decision, not one where you observed it.
- Name the disagreement or constraint, and how you resolved it with evidence.
Follow-up
- What did you decide not to do, and why?
- How did you know the outcome was caused by your change?
How do you handle a situation where a client's business requirements a…
How do you handle a situation where a client's business requirements are ambiguous or change mid-project?
Approach
- Name the disagreement or constraint, and how you resolved it with evidence.
- Quantify the outcome, including what you would not claim credit for.
- Pick a story where you drove the decision, not one where you observed it.
Follow-up
- What would you do differently if you ran that project again?
- What did you decide not to do, and why?
Walk through an analysis you later discovered was wrong
Six weeks ago you reported that consumption fell 9 percent in the last week of the month, and a team spent a sprint investigating the cause. The fall was an artefact: rows in fct_usage_daily land late and are restated in place, and you queried before the tail had settled. Describe how you found the error, what you told the people who acted on it, and the control you put in place so this class of mistake cannot reach a dashboard again. Be specific about how the settling window was measured.
Approach
- The interviewer is probing whether you self-report errors before someone else finds them, and whether your fix is structural rather than a promise to be more careful. Say plainly that the number was wrong and that a sprint was spent on it, before describing any diagnosis.
- Establish the artefact quantitatively instead of asserting that data lands late. For each usage_date, compare the total as of first_written_at against the settled total and read the settling time off that curve, for example 97 percent of final by day three and 99.5 percent by day five.
- Correct the record the same day, in the channel the original number went out in, to the same audience. The cost of the wasted sprint belongs in the correction, not in a footnote.
- Make the fix structural: exclude a trailing lag window from every reportable figure, and make the reporting view return no rows inside that window rather than returning partial ones. A dashboard that shades unsettled days still gets read as a decline.
- State what generalises. Any fact table restated in place has this failure mode, so the guard belongs at the source rather than on the one dashboard that embarrassed you. A strong answer ends with the class of error closed; a generic one ends with a lesson learned.
Follow-up
- How did you choose the completeness threshold behind the lag window, and what would make you recalibrate it?
- What did you say to the team that lost the sprint, and what did they say back?
- Is there a legitimate case for showing the unsettled tail at all, and to whom?
- 01
Walk me through a complex data science project from your resume, focusing on your specific contributions and the business outcomes.
- 02
How do you handle a situation where a client's business requirements are ambiguous or change mid-project?
- 03
Six weeks ago you reported that consumption fell 9 percent in the last week of the month, and a team spent a sprint investigating the cause. The fall was an artefact: rows in fct_usage_daily land late and are restated in place, and you queried before the tail had settled. Describe how you found the error, what you told the people who acted on it, and the control you put in place so this class of mistake cannot reach a dashboard again. Be specific about how the settling window was measured.
Is this an official People Tech Group interview guide?
No. It is PracHub's own research and practice material for the Data Scientist role at People Tech Group. Rounds and questions reflect what candidates have reported, not a process People Tech Group has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗What is the typical timeline for the hiring process at People Tech Group?
The entire process usually takes between 2 to 4 weeks from the initial HR screen to the final offer. However, the timeline can be significantly shorter if there is an urgent client project alignment, sometimes concluding in a single week.
PracHub interview research ↗How technical is the first round coding assessment?
The coding assessment focuses heavily on data science fundamentals and model building. You should expect questions that test your ability to manipulate data, implement baseline models, and perform parametric comparisons of different algorithms rather than complex, abstract LeetCode-style dynamic programming.
PracHub interview research ↗Does People Tech Group support remote or hybrid work environments?
Working models depend heavily on the specific team, office location, and client requirements. While many teams operate on a hybrid schedule, you should clarify expectations with your recruiter during the initial HR round.
PracHub interview research ↗How much emphasis is placed on Generative AI vs. Classical Machine Learning?
Both are highly valued. While classical machine learning (regression, classification, clustering) forms the foundation of the technical evaluation, having practical experience with LLMs, prompt engineering, and RAG architectures is a significant differentiator that aligns with the company's current strategic focus.
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