Interview guides · DRT Strategies
DRT Strategies Data Scientist Interview Questions & Guide 2026
Case practice for DRT Strategies data scientist candidates: scope a vague prompt into a measurable question before you analyze it.
The 60-second brief
As a Clinical Data Scientist at DRT Strategies, you serve as a pivotal bridge between complex clinical data and the regulatory oversight of the FDA’s Office of New Drugs (OND). Your work is not just about crunching numbers; it is about ensuring the safety and efficacy of new drug applications by providing rigorous, evidence-based analytical support to multi-disciplinary review teams. You are a problem solver who applies advanced statistical and data science methodologies to verify the integrity of safety data submitted by pharmaceutical sponsors.
Most of the loop measures decision-making under uncertainty rather than recall. You are scored on whether you state your assumptions, commit to an estimate you can defend, and say explicitly what evidence would change it.
Focus areas
- Minimise protected health information in every extract
- Correct for claims runout before reporting recent months
- Separate censoring from events in time-to-event models
Overview
The impact of this role is significant. By analyzing adverse event reports, trial designs, and laboratory safety data, you help FDA staff make informed, high-stakes risk determinations that directly affect public health. You will collaborate with medical officers and statistical reviewers, translating technical findings into clear, actionable scientific reports. This position is ideal for a candidate who thrives in a mission-driven, consulting-oriented environment where precision, clear communication, and deep technical expertise are paramount.
While you provide critical analytical support, always remember that you are in a contractor role. Your work is subject to review by federal employees, so emphasizing your ability to produce high-quality, audit-ready documentation is key to success.
The DRT Strategies interview process
DRT Strategies candidates report 3 rounds · ≈ 3-5 weeks. The stages below are what candidates describe, not a published process.
Initial Screening
Whoever runs this call is usually not a practitioner. They take notes, and a hiring manager skims those notes later, so the real question is whether your work survives being written down by someone outside the field. Test every project sentence against that: could a non-specialist repeat it correctly without knowing what a propensity score is? Carry a plain-language version of each project and one reason you want this particular role that you could not copy onto another application. Vagueness at this stage reads as inexperience, even when the underlying work was genuinely deep.
What to demonstrate
- Whether a non-specialist can restate your projects accurately, since their paraphrase is what reaches the hiring manager
- Whether your reason for wanting the role points at the work itself rather than the company's reputation
- Whether your language signals the level being screened for: what you decided yourself versus what you were handed
How to prepare
- Write a two-sentence, jargon-free version of each major project: the question nobody could answer, and the decision your work changed. Read it to someone outside data and have them repeat it back
- Point your 'why this role' answer at something concrete in the job description or the product surface you would be working on, and keep it to two sentences
- Have two questions ready about measurement: which metric the team is held to, and who acts on an analysis once it lands
Technical Screening
This round decides whether someone can hand you a schema and a question and trust the number that comes back. Correctness under a clock is the bar, not clever syntax. The habit that separates strong from weak answers is checking the grain: after every join, know how many rows you expect and whether the count moved. Most wrong answers in this format are not wrong logic, they are a fan-out from a key that turned out not to be unique, or a filter applied before an aggregate when it belonged after. Say what you expect before you run it.
What to demonstrate
- Whether your row counts survive each join, and whether you notice on your own when they do not
- Deliberate handling of rows that fail to match, including whether the question needs an inner join or a left join with the non-matches kept and counted
- Whether NULLs are treated on purpose, given that a NULL compares equal to nothing and that COUNT of a column skips it
- Reaching a defensible answer inside the window instead of a refined one after it
How to prepare
- Take a two-table schema, write a join that fans out on purpose, then fix it by collapsing the many-side to one row per key before joining. Repeat until the fix is reflex rather than recall.
- Write a funnel as one query and print the distinct user count at each stage, then confirm each stage is a subset of the one above it rather than assuming it
- Do a few timed runs in a plain text box with no autocomplete and no formatter, since assessment editors often have neither
Panel Interviews
Where 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
Where candidates lose points
Reading the most recent months of a claims-based series as real
Claims incur before they are reported and paid, so recent incurred months are systematically undercounted until runout completes. The lag is not uniform: pharmacy adjudicates in days, professional claims in weeks, inpatient facility claims in months. That means recent data is both too low and mix-shifted toward cheap services, which reads as a cost improvement and a utilisation drop at once. The fix is to hold the last three incurred months back or apply completion factors, and to state the paid-through date on every chart.
Pre-post evaluation on a high-cost or high-risk cohort
Cohorts selected on an extreme value of the outcome regress toward the mean on their own. Members identified as the top 1 percent of spend in one year spend far less the next, whether or not anyone intervenes, because the selecting year captured both chronic severity and one-off events. A pre-post design on such a cohort will report savings every time. A concurrent comparison group selected by the same rule in the same period, or a regression discontinuity at the selection threshold, is the minimum credible design.
Reading an observational correlation as a causal effect
Name the confounder you are most worried about and the design that would remove it: an experiment, a difference-in-differences with a checked pre-period trend, an instrument, or a regression discontinuity. When none is available, state which direction the bias likely runs and bound the claim accordingly.
Never asking what decision the analysis will inform
Open with who makes the decision, what the options are, and by when. The answer determines the precision you need, the segments worth cutting, and whether an observational read suffices or an experiment is required.
Questions & practice
Bootstrap a confidence interval for a ratio-of-sums PMPM
Medium · bootstrap · ratio estimator · resampling unit
You have one row per member for a fully run-out incurred year: member_id, member_months, allowed_amount. Report allowed PMPM, defined as sum(allowed_amount) divided by sum(member_months), with a 95 percent confidence interval from a bootstrap you write yourself. No library resampler. Resample members with replacement, recompute the ratio on each of 2,000 replicates, take a percentile interval, and seed the generator so the result reproduces. In two sentences, state why resampling claim lines instead of members would be wrong.
Approach
- Name the estimator precisely: PMPM is a ratio of sums, not the mean of per-member ratios. The two differ whenever exposure correlates with spend, and it does, because members who churn out mid-year are systematically different from members covered all twelve months.
- Resample the unit of independence, which is the member, and recompute numerator and denominator together on the same draw. Recomputing only the numerator against a fixed denominator understates variance and is a common slip.
- Pull member_months and allowed_amount into numpy arrays once, then draw indices with rng.integers(0, n, size=n) per replicate. Index draws over arrays run one to two orders of magnitude faster than DataFrame.sample, which is the difference between 2,000 replicates and 200.
- Take the 2.5th and 97.5th percentiles of the replicate ratios. Expect an interval that is asymmetric around the point estimate, because healthcare spend is right skewed. That asymmetry is the method working, not a bug to centre away.
- Answer the line-resampling question concretely: the many lines of one high-cost member are not independent draws, so line resampling shrinks the interval toward zero width, and member_months has no line-level analogue, so the denominator becomes undefined.
Follow-up
- Half a percent of members have a transplant or a long NICU stay. Does a percentile interval still have nominal coverage, and what would you do about the tail?
- The question changes to comparing PMPM across provider panels. What becomes the resampling unit and why?
- How would you use the same replicates to test whether this year's PMPM differs from last year's, given the same members appear in both?
Four data-quality rules over corrected and cancelled lab results
Easy · data quality · record supersession · unit drift
lab_result has result_id, order_id, patient_id, loinc_code, value_numeric, value_text, units, reference_low, reference_high, specimen_collected_ts, resulted_ts, result_status (preliminary, final, corrected, cancelled), supersedes_result_id. Return one row per rule with a failing count, a failing share, and one example result_id, for these rules: more than one surviving row per (order_id, loinc_code) after resolving corrections and dropping cancelled; resulted_ts earlier than specimen_collected_ts; a numeric result whose unit is not the modal unit for its loinc_code; value_numeric and value_text both null on a row with result_status 'final'.
Approach
- Resolve the correction chain before anything else. Drop result_status 'cancelled', then within each (order_id, loinc_code) keep the row whose result_id appears in no other row's supersedes_result_id. That terminal node is the surviving value and the rule holds even if a correction is loaded with a backdated timestamp.
- Build each rule as a boolean mask over a named frame rather than as a filtered copy, so the failing share has an explicit, per-rule denominator. Rule three is eligible only on rows with a non-null value_numeric; rule four only on final rows.
- For the unit rule, derive the modal unit per loinc_code from the data instead of hardcoding an expected unit. The failure being hunted is one analyte reported in two units whose values differ by a fixed factor, which no range check catches because both sets of numbers look plausible.
- Emit a tidy frame with columns rule, eligible_rows, failing_rows, failing_share, example_result_id. A printed report cannot be diffed between runs; a frame can be stored and alerted on.
- Order the output by failing_share descending so the run has a lead finding rather than four equal-weight lines.
Follow-up
- The modal-unit rule fires on 8 percent of one analyte. How do you decide whether that is a unit-conversion bug or a second legitimate assay?
- What would you add to catch a value that is inside its reference range but physiologically impossible?
- Which of these four rules should block a downstream pipeline and which should only alert, and why?
Simulate how ignoring clustering inflates the false positive rate
Medium · simulation · design effect · type i error
Simulate a provider-level comparison with no true effect. 40 providers, 60 members each, a continuous outcome with total variance 1 and intraclass correlation 0.02. Randomise providers 20 to 20, not members. Over 5,000 replications, report the share of replications where a two-sample t-test run on all 2,400 individual observations, ignoring provider, returns p below 0.05. Report the same share when the unit of analysis is the 40 provider means. Then state how the first number follows from the design effect 1 + (m - 1) x ICC.
Approach
- Decompose the variance explicitly rather than tuning it: provider variance = ICC = 0.02, residual variance = 1 - ICC = 0.98. Draw u_j once per provider and e_ij per member, so the outcome is u_j + e_ij and the correlation between two members of one provider is 0.02 by construction.
- Randomise at the provider level. That is the entire mechanism: the treatment indicator is constant within a provider, so in any single replicate the provider intercepts are confounded with the arm, and the naive test reads that confounding as signal.
- Vectorise over replications with a (reps, providers, members) array. 5,000 x 2,400 normals is trivial in numpy, and a Python loop is what tempts people to cut replications to 500 and report a number with Monte Carlo noise of plus or minus 0.017.
- Predict the answer before running it: design effect = 1 + (60 - 1) x 0.02 = 2.18, naive standard errors are too small by sqrt(2.18) = 1.476, so the rejection rate at nominal 0.05 is about 2 x (1 - Phi(1.96 / 1.476)) = 0.18. Agreement between prediction and simulation is what makes the result a demonstration rather than an anecdote.
- Run the provider-mean analysis as the control. Recovering 0.05 there proves the generator is correct and isolates the failure to the analysis unit.
Worked solution (30 min)
- Draw u with shape (reps, 40) from N(0, sqrt(0.02)) and e with shape (reps, 40, 60) from N(0, sqrt(0.98)); y = u[:, :, None] + e.
- Assign providers 0-19 to one arm and 20-39 to the other; because there is no true effect, a fixed split is valid and removes one source of Monte Carlo noise.
- Naive test: flatten each arm to 1,200 observations and compute a two-sample t statistic per replication with vectorised means and pooled variance.
- Cluster test: average within provider to 40 values, then run the same two-sample t on 20 versus 20.
- Report both rejection shares and compare the naive one against 2 x (1 - Phi(1.96 / sqrt(2.18))).
Expected result: The naive individual-level test rejects in roughly 18 percent of replications, against a nominal 5 percent. Monte Carlo standard error at 5,000 replications is about 0.005, so anything in 0.17 to 0.19 is consistent. The provider-mean analysis rejects in about 5 percent, within roughly 0.003.
Verify it yourself
- Set ICC to 0 and both analyses return about 0.05. If the naive one does not, the data generator is wrong, not the test.
- Raise members per provider from 60 to 120 with ICC fixed and the naive rate rises, because the design effect grows linearly in cluster size.
- The provider-mean analysis stays near 0.05 at every ICC you try, which is the definition of a valid test.
- The simulated naive rate lands within about 0.01 of 2 x (1 - Phi(1.96 / sqrt(design effect))).
Follow-up
- How many providers would you need for 80 percent power on a 0.2 SD difference with 60 members each and this ICC?
- Cluster sizes are unequal in reality. The design effect approximation becomes 1 + ((1 + CV^2) x mbar - 1) x ICC. Which direction does that move your sample size and why?
- The intervention cannot be withheld from any provider. Sketch a design that still yields a defensible estimate.
Count thirty-day unplanned readmissions without counting transfers
Medium · self-join · event streams · exclusions
encounter holds encounter_id, patient_id, facility_id, encounter_type, admit_ts, discharge_ts, admission_type, discharge_disposition, is_planned_admission and index_encounter_id. For inpatient stays discharged between 2025-01-01 and 2025-11-30, return the 30-day unplanned readmission rate overall and by facility_id. Exclude an index stay when is_planned_admission is TRUE or discharge_disposition is transfer_acute, expired, hospice or ama. A qualifying readmission is any unplanned inpatient admission for the same patient with admit_ts after the index discharge_ts and within 30 days of it. One stay can be both a readmission and the next index stay.
Approach
- Decide between LEAD and EXISTS explicitly and say why. LEAD over the patient's admission stream gives the literal next stay, so an intervening planned admission hides a later unplanned one. The measure asks whether any unplanned admission fell in the window, which is an EXISTS or a self-join with a range predicate.
- Exclude transfers at the index end before anything else. An acute-to-acute transfer closes one encounter and opens another at a different facility_id within hours, so without the transfer_acute exclusion the facilities that move the sickest patients out look the worst.
- Apply the index exclusions as a set, including stays with NULL discharge_ts, which are still open and have no measurable window.
- Stop the denominator early enough that every index stay had a full 30 days of observation plus encounter lag. That is why the window ends 2025-11-30 rather than at year end.
- Compute the rate at stay level, not patient level, then compare the raw facility rates against an observed-over-expected framing before anyone publishes a ranking.
Follow-up
- A patient has three stays ten days apart. How many index stays and how many readmissions, and why does the answer depend on the stated rule?
- Which comparison would you publish across facilities, raw rate or observed over expected, and what does risk adjustment still fail to fix?
- index_encounter_id already exists on the table. Would you trust it, and how would you audit it against your own logic?
Compute allowed PMPM by incurred month without span fan-out
Hard · fan-out · many-to-many · runout
Report allowed PMPM by incurred month and product_type for 2025 from medical_claim_line (member_id, claim_id, claim_version, frequency_code, service_start_date, allowed_amount, claim_status), pharmacy_claim (member_id, fill_date, allowed_amount, reversal_flag, reversed_fill_id), member_enrollment (span_id, member_id, product_type, effective_date, termination_date) and member_risk_score (member_id, score_year, prospective_risk_score), which holds at most one row per member per score year. The numerator is allowed_amount on surviving claim versions plus unreversed fills, attributed to the product_type in force on the service or fill date. The denominator is member-months. Also return a risk-adjusted PMPM for each cell: allowed PMPM divided by the member-month-weighted mean prospective_risk_score for score_year 2025 over the members making up that cell's denominator. A colleague joined claim lines to member_enrollment on member_id alone and the annual total came back 1.4 times the finance figure. Diagnose that, then produce the correct monthly series.
Approach
- Name the defect precisely. member_enrollment is one row per span, so joining on member_id alone is one-to-many and duplicates every claim line once per span that member ever held. The inflation factor is the spend-weighted mean span count per member, which is why 1.4 is plausible and why it is not a constant you can divide back out.
- Make the join functional: member_id AND service date between effective_date and COALESCE(termination_date, DATE '9999-12-31'). That yields at most one span per line unless spans genuinely overlap, in which case pick a documented precedence rule, most recently effective wins being the usual one, and prove uniqueness with a duplicate check rather than asserting it.
- Aggregate numerator and denominator separately and join them on (month, product_type). Computing both sides across one join is the second route to inflation, because the member-month denominator fans out over claim lines just as easily as the dollars fan out over spans.
- Clean each numerator source on its own terms: surviving claim versions with voids removed and claim_status 'paid' on the medical side, reversal rows and their originals removed on the pharmacy side.
- Apply completion before anyone reads a trend. State the paid-through date and either withhold the three most recent incurred months or apply completion factors, since the lag differs by service type and the incomplete tail reads as a cost improvement and a utilisation drop at once.
- Risk-adjust last, and weight the score the way the denominator is weighted. The divisor for a cell is SUM(member_months * prospective_risk_score) / SUM(member_months) over that cell's members, not a plain AVG over distinct members: a member covered two months must not count the same as one covered twelve. member_risk_score is member-level, so join it after the member-month grain is fixed, or it becomes a second fan-out.
- State the rule for members with no 2025 member_risk_score row: keep them in member_months, leave them out of the weighted mean, and publish the scored share of member-months beside the adjusted series. A thin score table moves the adjusted number while the raw one sits still, and without that share nobody can tell the two apart.
Worked solution (45 min)
- CTE med: surviving claim version per claim_id, voids dropped, claim_status 'paid', service_start_date in 2025.
- CTE rx: fills with reversal_flag FALSE and not referenced by any reversed_fill_id, via NOT EXISTS, fill_date in 2025.
- Attribute each numerator row to one span with the date-bounded join, after asserting that row counts before and after the join are equal.
- CTE denom: member-months by month, product_type and member_id from spans alone, with fractional partial months and overlapping spans collapsed first.
- Join numerator to denominator aggregated on (incurred_month, product_type) and divide for allowed_pmpm.
- Join denom to member_risk_score on member_id for score_year 2025, compute the cell divisor as SUM(member_months * prospective_risk_score) / SUM(member_months) over scored members, carry the scored share of member-months, and divide allowed_pmpm by the divisor for risk_adjusted_pmpm.
- Withhold the three most recent incurred months and label the paid-through date on every row.
Expected result: One row per (incurred_month, product_type) with allowed_medical, allowed_pharmacy, member_months, allowed_pmpm, mean_risk_score, scored_member_month_share and risk_adjusted_pmpm, covering January through September when the paid-through date is year end and three months are withheld. Row count of the claim-line set is identical before and after the enrollment join.
Verify it yourself
- Claim-line row count before and after the span join is unchanged. An increase is fan-out; a decrease is a service date with no covering span, which is a real finding about eligibility gaps.
- SUM(allowed_amount) across product_types for a month equals the ungrouped monthly total computed without touching member_enrollment at all.
- member_months for a month never exceeds the count of distinct members covered at any point in that month.
- mean_risk_score for a cell lies between the minimum and maximum prospective_risk_score among its scored members, and risk_adjusted_pmpm equals allowed_pmpm exactly when that mean is 1.0. If the weighted mean equals a plain AVG over distinct scored members in every cell, the member-month weights were never applied.
- A downward step in the last reported months means the runout holdback was not applied; the withheld tail should not be visible in the series at all.
Follow-up
- A member holds two overlapping spans under different product_types on the service date. Which one gets the dollar, and how do you keep the member-month denominator consistent with that choice?
- Write the check that proves the span join is one-to-one rather than assuming it.
- Finance reports on paid_date and you reported on service_start_date. Reconcile one month between the two bases.
How do you approach the detection of safety signals in clinical trials, such as identifying trends in TEAEs (Treatment-Emergent Adverse Events)?
Medium · product sense and metrics
Approach
- Restate the decision this analysis has to support, and who acts on the answer.
- Fix the population and the time window before naming any metric.
- State what result would change your recommendation, so the answer is falsifiable.
Follow-up
- 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 would you perform a time-to-event analysis to assess safety outcomes in a clinical trial?
Medium
Approach
- Work from the decision backwards to the evidence you would need.
- Clarify what is being asked and what a complete answer would contain.
- Say what you would check first and why it is the highest-information step.
Follow-up
- What assumption would you test first?
- How would you know your answer was wrong?
Explain your process for verifying data submitted by a sponsor against the raw data provided in an NDA or BLA.
Medium
Approach
- Clarify what is being asked and what a complete answer would contain.
- Work from the decision backwards to the evidence you would need.
- State your assumptions explicitly before working the problem.
Follow-up
- How would you know your answer was wrong?
- What assumption would you test first?
Reduce variance on a skewed cost outcome with CUPED
Medium · cuped · variance reduction · stratification · skewed outcomes
A member-randomised digital care programme will be read on 12-month allowed PMPM, built from surviving medical_claim_line versions plus unreversed pharmacy_claim rows over member-months from member_enrollment. The outcome is heavily right-skewed. Eighty percent of members have 12 months of prior continuous coverage and therefore a usable pre-period PMPM; among those, the correlation between pre-period and post-period member PMPM is 0.45. Propose a variance reduction plan, quantify the expected gain, and say how you handle the 20 percent with no pre-period.
Approach
- Apply CUPED with the pre-period PMPM as the covariate: theta = Cov(Y, X) / Var(X), and Y_adj = Y - theta x (X - mean(X)). Because X is measured strictly before randomisation it cannot be affected by treatment, so the adjusted difference in means stays unbiased while its variance falls by the factor 1 - rho^2.
- Quantify honestly: rho = 0.45 gives 1 - 0.2025 = 0.80, a 20 percent variance reduction inside the covered stratum, which is a real but modest gain. Do not quote consumer-experimentation figures of 40 to 50 percent, which come from outcomes far more autocorrelated than health spend.
- Handle the skew before handling the covariate. Pre-specify a truncation point (a percentile of the prior year, or a fixed stop-loss amount) applied identically to both arms and fixed before unblinding, and state plainly that you are now estimating an effect on truncated cost. Report the untruncated result as a secondary so nobody can claim the cap created the finding.
- Do not impute a mean pre-period for the 20 percent with none. Stratify: run CUPED inside the covered stratum, take the unadjusted difference in the no-pre-period stratum, and combine with fixed weights; equivalently, regress with a missingness indicator and an indicator-by-covariate interaction. Both keep the estimator unbiased because the stratum is defined pre-randomisation.
- Get some of the same gain for free at assignment time by stratifying or covariate-constrained randomisation on prior-year cost decile, which removes the post-hoc analytic choices that a sceptical reviewer will otherwise interrogate.
Worked solution (30 min)
- Estimate theta on the full randomised sample as Cov(Y, X) / Var(X), using both arms because X is pre-treatment.
- Form Y_adj = Y - theta x (X - mean(X)) inside the covered stratum and compute the variance ratio 1 - rho^2 = 1 - 0.45^2 = 0.80.
- Combine strata: assuming equal per-member outcome variance, the overall variance of the treatment-effect estimate falls by about 0.8 x 20 percent = 16 percent.
- Translate to MDE: sqrt(0.84) = 0.916, so the MDE falls about 8 percent; equivalently you save about 16 percent of the sample at fixed MDE.
- Validate on a historical A/A split: CUPED should return an effect indistinguishable from zero with the claimed variance reduction.
Expected result: theta = Cov(Y, X) / Var(X); variance falls to 0.80 of baseline inside the 80 percent with a pre-period, about 16 percent overall under equal per-member variance, which shrinks the MDE by roughly 8 percent. The no-pre-period members enter as their own stratum, never as imputed means.
Verify it yourself
- theta should be close to rho x sd(Y) / sd(X); a large gap points at an outlier driving the covariance.
- The CUPED and unadjusted treatment-effect point estimates should be close; a large divergence means X is not pre-treatment or the cap is doing the work.
- Re-estimate rho after truncation, since capping both tails usually moves it.
- Run the whole procedure on a historical A/A period and confirm a null effect with narrower intervals.
Follow-up
- rho drops to 0.20 after truncation. What do you do with the CUPED plan?
- Members with no pre-period are new enrollees. What does that do to your assumption of equal per-member variance across strata?
- Would you switch the estimand from mean PMPM to a rank-based or log-scale comparison, and what would that cost you with a finance audience?
Adherence share collapsed the month a feed was added
Easy · pdc · interval sql · identity resolution
The share of members with proportion of days covered at or above 0.80 in one therapeutic class fell from 0.71 to 0.58 in a single month. pharmacy_claim carries fill_id, member_id, ndc_code, therapeutic_class_code, fill_date, days_supply, quantity_dispensed, refill_number, reversal_flag, reversed_fill_id and source_system_code. There is no person-level key above member_id and no enrollment table on hand, so every diagnostic has to run on pharmacy_claim alone. That month the pipeline began ingesting a second pharmacy source. Determine whether adherence actually changed, and hand back a PDC query you would defend line by line.
Approach
- Compute controls that depend on neither member identity nor the PDC code: total fills in the class per month, and total days_supply dispensed in the class per month. Both are sums over rows, so neither moves when one person's fills split across two member_ids, which is exactly what a per-member control cannot promise. If both are flat while PDC falls, no dispensing behaviour changed and the computation or the keys did.
- Check days_supply for nulls and zeros by source_system_code. If the new source omits days_supply and the code coalesces null to zero, covered days vanish and PDC falls even though the fills are there.
- Check for member identity splitting using the columns you actually have. There is no person key above member_id, so the split has to be found by its footprint: distinct member_id in the class jumping at the break while total fills stay flat, and a rise in the share of member_ids whose earliest fill for a given ndc_code carries refill_number above zero, which is a continuation history that lost its beginning. When one person is split, each id may fall below the two-fill denominator requirement and drop out, and the ids that do survive carry artificial gaps.
- Check reversals. A reversed fill is two rows, the fill and a row with reversal_flag TRUE pointing at reversed_fill_id, and both must be excluded from exposure. If the new source expresses reversals differently and reversed_fill_id does not link, phantom coverage appears, which pushes PDC up rather than down, so use this to rule the cause in or out.
- Verify the denominator and window are unchanged: members with at least two fills in the class and at least 91 days of follow-up, over a stated fixed 12-month window, never a mixture of window lengths.
- Write the PDC query so overlapping refills shift the next interval's start to the later of fill_date and the prior interval's end, so a day is covered at most once, and cap at one day per calendar day.
Follow-up
- Why is PDC preferred to medication possession ratio when early refills are common?
- You want to compare adherent and non-adherent members on hospitalisation. What is wrong with classifying on a 12-month PDC and then following from day zero?
- A member switches to a different drug in the same class mid-year. How does your interval logic handle that, and is the class the right grain?
Suggested practice checklist
Instead of guessing where the week should go, day one measures it under a fixed rubric and allocates the remaining hours in proportion to the gaps. The method is deliberately rigid: the allocation is written down before any studying starts and is not renegotiated when a topic turns out to be unpleasant.
Day 1 — Diagnostic, scored before you study anything
- Sit a 100-minute timed diagnostic in four blocks: 30 minutes of SQL across three prompts, 25 minutes of short-answer statistics, 25 minutes on one modelling or case prompt, and 20 minutes delivering one behavioural story aloud.
- Score each block from 0 to 3 on a fixed rubric where 3 is correct and fluent, 2 is correct but slow or prompted, 1 is partially correct, and 0 is stuck, grading the output rather than how the attempt felt.
- Allocate the hours for days two to five roughly in proportion to 3 minus the score in each block, write the allocation down, and commit to not revising it midweek.
Deliverable: A scored rubric and a fixed hour allocation for the rest of the week.
Day 2 — Largest gap: find the boundary rather than the subject
- Break the weakest area into five named sub-skills (for query work: grain control, window frames, date arithmetic, set logic with NULLs, and reading a query plan) and rate each one, so the rest of the week targets a sub-skill instead of a subject.
- Solve three problems chosen to sit just above where the rating drops off, and for each write the first move you failed to make.
- Re-solve one of them from memory four hours later, on paper, with nothing open.
Deliverable: A five-item sub-skill map with the two blocking sub-skills circled.
Day 3 — Largest gap: drill the blocking sub-skill
- Do eight short repetitions of the same shape rather than eight different problems, so what you practise is the pattern and not the puzzle.
- Write the rule you now hold in one sentence, then test it against a case built to break it: a ranking function over a column with ties, or a two-sample test on observations that are obviously dependent.
- Have someone else read your one-sentence rule and find the precondition you left out.
Deliverable: One rule statement with its preconditions attached and one counterexample that would have caught the incomplete version.
Day 4 — Second gap, plus maintenance on your strongest area
- Run the same sub-skill map and boundary protocol on the second-largest gap, compressed into half the day.
- Spend 25 timed minutes on your strongest area to stop it decaying, choosing the hardest problem you can still finish rather than an easy warm-up.
- Compare how the two areas fail: whether you lose time on recall, on setup, or on arithmetic, because the fix differs for each.
Deliverable: A second sub-skill map plus a one-line diagnosis of how each area fails you.
Day 5 — The gap that is not a skill
- Record yourself answering one technical and one behavioural prompt, then count two things in the playback: how many seconds before your first clarifying question, and how many sentences you started without knowing where they ended.
- Rewrite your three most-used stock phrases into shorter versions, and practise saying "I do not know, here is how I would find out" without softening it into a guess.
- Deliver one answer again with a hard 90-second limit to force structure before detail.
Deliverable: Two recordings with a counted improvement in time-to-first-question.
Day 6 — Retest under day-one conditions
- Sit the same 100-minute diagnostic structure with new prompts of comparable difficulty and score it on the identical rubric.
- Compare block by block, and for any block that did not move, change the method rather than adding hours: a block stuck at 1 usually means the practice was too varied, not too short.
- Write which single block you would still lose the offer on.
Deliverable: A second scored rubric placed next to the first, with one named remaining risk.
Day 7 — Full loop under interview conditions
- Run a 60-minute mock covering the two blocks that moved least, with an interviewer instructed to interrupt and change direction.
- Write your recovery script for the moment you go blank: restate the question, state your assumption, name the first thing you would check.
- Reduce the week to the rule statements you wrote, each with its preconditions attached, then say every one of them out loud without reading it and cut any you cannot state in a single sentence, since a rule you have to reconstruct mid-answer will not survive being interrupted.
Deliverable: A one-page card holding the recovery script and only the rules you could state from memory.
Where your data came from
Data people depend on systems owned by other teams, and much of the job is negotiating for instrumentation, access, or a fix to a broken pipeline. Prepare an example of getting something changed upstream that you did not control. Describe what you asked for, what you traded, and how you worked while you waited.
Can you describe your experience with SDTM and ADaM datasets? Which specific domains (e.g., ADAE, ADLB) have you worked with most extensively?
Medium · behavioural and stakeholder questions
Approach
- Pick a story where you drove the decision, not one where you observed it.
- Close with what you would do differently, concretely.
- Name the disagreement or constraint, and how you resolved it with evidence.
Follow-up
- What would you do differently if you ran that project again?
- How did you know the outcome was caused by your change?
Describe a time you had to explain a complex statistical finding to a medical professional or non-data scientist. How did you ensure clarity?
Medium · behavioural and stakeholder questions
Approach
- State the situation in two sentences and spend the rest on your reasoning.
- Quantify the outcome, including what you would not claim credit for.
- Name the disagreement or constraint, and how you resolved it with evidence.
Follow-up
- What would you do differently if you ran that project again?
- How did you know the outcome was caused by your change?
How do you handle tight, mandatory deadlines when working on multiple drug application reviews simultaneously?
Medium · behavioural and stakeholder questions
Approach
- Name the disagreement or constraint, and how you resolved it with evidence.
- 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.
Follow-up
- What would you do differently if you ran that project again?
- How did you know the outcome was caused by your change?