cswork / libraryOpen practice workspace

Interview guides · Hitachi Energy

Hitachi Energy Data Scientist Interview Questions & Guide 2026

Diagnose a metric move for Hitachi Energy data scientist prep: split by segment, rule out a logging change, separate mix shift from behaviour.

The 60-second brief

A Data Scientist at Hitachi Energy serves as a strategic bridge between complex industrial data and actionable business intelligence. As the company powers the transition toward a sustainable energy future, your work directly influences how global energy grids are managed, optimized, and maintained. Whether you are working on financial forecasting or operational efficiency, your models and insights are foundational to the company's commitment to delivering reliable, sustainable energy.

SQL is seldom the hardest round and is often the one that eliminates people. The working bar is usually window functions, correct deduplication, and joins that do not silently fan out rows, rather than obscure syntax.

Focus areas

  • Trace an on-time miss to one node
  • Join daily snapshots to shipment events safely
  • Evaluate forecasts at the lag ordering actually uses

Overview

The role is inherently cross-functional, requiring you to translate ambiguous business requirements into robust data solutions. You will collaborate with engineering, product, and finance teams to solve high-stakes problems, such as identifying metric drops in operational dashboards or designing experiments to validate energy usage models. It is a position that demands both technical rigor and the ability to articulate complex findings to stakeholders who may not have a technical background.

The Hitachi Energy interview process

Hitachi Energy candidates report 2 rounds · ≈ 2-4 weeks. The stages below are what candidates describe, not a published process.

Initial Conversation

An 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.

Technical Round

Much 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

Where candidates lose points

Attributing demand variability to the node where it is observed

Order variance amplifies as it moves upstream: batching to a truckload, minimum order quantities, forecast-driven ordering and promotional pull all convert smooth end demand into lumpy replenishment orders, so a plant can see a coefficient of variation several times that of the underlying consumption. Diagnosing the plant's schedule instability as a plant problem then produces interventions that cannot work, because the generating process sits one or two echelons downstream. Measure the bullwhip ratio explicitly (variance of orders placed by a node over variance of demand it received) at each echelon, and fix the ordering rule at the node where the ratio jumps rather than the node where the pain is felt.

Sizing safety stock as z times sigma_D times the square root of lead time

That form assumes lead time is deterministic. When lead time itself varies, the standard deviation of demand over lead time is sqrt(L_bar * sigma_D^2 + D_bar^2 * sigma_L^2), and the second term dominates whenever supply is unreliable, so the familiar formula can understate the requirement severalfold for a long, variable inbound lane. Two further preconditions are routinely forgotten: demand is assumed independent across periods, which promotions and order batching break, and z maps to cycle service level (the probability of no stockout in a replenishment cycle), not to fill rate, which additionally depends on order quantity through the unit normal loss function. Quoting a z-derived number as a fill rate overstates achieved service, and the gap widens as order quantity shrinks.

Building features from data that postdates the prediction time

Check every feature against the timestamp at which the model would actually score, and drop anything computed from a window that includes or follows the label event. For a forecasting use case, split train and test by time rather than at random, and split by entity when the same entity recurs.

Reading experiment results before checking the arm split

Compare observed arm counts against the intended allocation ratio, not an assumed even split, and set the alarm far below the conventional 0.05: at 0.05 roughly one healthy experiment in twenty trips it, which is why sample-ratio checks usually run at p < 0.001 or stricter. The test's power scales with sample size, so it misses a real diversion on a small experiment and fires on an imbalance too small to move the estimate on a very large one. A flag means go find the assignment or logging fault before reading any outcome, not report a mismatch.

Questions & practice

Give an example of a project where you took initiative to improve an existing process or model.

Medium · machine learning and modelling

Approach

  1. Check what information would not exist at prediction time, and exclude it.
  2. Set a baseline first, so any model has something honest to beat.
  3. 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?

Recover unconstrained demand from stockout-censored history

Hard · censoring · maximum likelihood · em algorithm

A legacy extract has only inventory_date, sku_id, location_id, shipped_qty and stockout_flag; demand_qty was not populated before a cutover date. On a stockout day, shipped_qty is a lower bound on that day's demand. Model daily demand per sku-location as Poisson and fit its mean by maximum likelihood, treating stockout days as right-censored observations. Return the fitted mean per cell alongside the naive mean of shipped_qty and the censored share. Then validate against the post-cutover window where demand_qty exists.

Approach

  1. Write the likelihood before any code. Uncensored days contribute the Poisson pmf at the observed count; stockout days contribute the survival probability P(X >= y), because all you learned is that demand was at least what you managed to ship.
  2. Solve it as an EM fixed point rather than reaching for a general optimiser: the censored MLE equals the complete-data mean with each censored observation replaced by its conditional expectation, so iterate lambda_next = (sum of uncensored y + sum of E[X | X >= y, lambda]) / n until it stops moving.
  3. Use the closed form for the conditional expectation rather than truncating an infinite sum: for a Poisson, sum over k >= y of k*p(k) equals lambda times P(X >= y-1), so E[X | X >= y] = lambda * P(X >= y-1) / P(X >= y) for y >= 1. That removes the tail-truncation error entirely.
  4. Refuse to fit cells with too little signal. A sku-location with three non-zero days or with every day censored has no identifiable mean; return the naive figure with a flag rather than a confident number.
  5. Validate on the post-cutover window where demand_qty is populated: fit the estimator on shipped_qty and stockout_flag alone, and compare both the censored estimate and the naive mean against the true mean of demand_qty.

Worked solution (45 min)

  1. Split each cell's days into censored (stockout_flag true) and uncensored, and record the censored share.
  2. Initialise lambda at the mean of shipped_qty over all days, which is a strict lower bound on the answer.
  3. Iterate the EM update using scipy.stats.poisson.sf for the survival terms, stopping when the change in lambda falls below 1e-8 or after 500 iterations.
  4. Assemble a per-cell frame with lambda_hat, naive_mean, censored_share, n_days and a converged flag; mark thin cells rather than fitting them.
  5. On the post-cutover window, compute the true mean of demand_qty per cell and report the absolute error of lambda_hat against the absolute error of naive_mean.

Expected result: Per-cell lambda_hat that is greater than or equal to the naive mean of shipped_qty in every cell, with equality exactly when the cell has no censored days. The uplift grows with censored share. On the validation window, lambda_hat has lower mean absolute error against the true demand_qty mean than the naive figure does.

Verify it yourself

  • Assert lambda_hat >= mean(shipped_qty) for every cell; the EM fixed point guarantees this because E[X | X >= y] >= y, so any violation is an implementation bug.
  • Re-solve one cell by directly minimising the negative log-likelihood with a one-dimensional optimiser and confirm it agrees with the EM answer to at least six decimal places.
  • Simulate a cell with known lambda, censor it artificially at a known threshold, and confirm the estimator recovers lambda within Monte Carlo error while the naive mean does not.
  • Confirm cells with zero censored days return lambda_hat exactly equal to the sample mean, since the likelihood reduces to the ordinary Poisson case.

Follow-up

  • The fitted mean is 18 percent above the naive mean for A-class items and 2 percent above for C-class. Why would you expect that ordering?
  • The residual variance is three times the fitted mean. What does that break and what distribution would you move to?
  • A stockout is often caused by a demand spike that day. What does that do to your estimate and can you correct it?

Cluster bootstrap for landed cost per delivered unit

Medium · bootstrap · clustering · ratio estimator · mix shift

You have delivered outbound legs from fct_shipment_leg: leg_id, shipment_id, leg_seq, carrier_id, origin_location_id, destination_location_id, shipped_units, cube_m3, linehaul_cost_cents, fuel_surcharge_cents, accessorial_cost_cents, expedite_premium_cents. In this extract the linehaul for a multi-stop load is booked entirely on leg_seq 1, so allocate it across the load's legs by cube first. Then estimate the difference in landed cost per delivered unit between two carriers on lanes both serve, with a 95 percent interval. Write the resampling yourself; no bootstrap library.

Approach

  1. Allocate the linehaul before anything else, in proportion to each leg's cube over the load's total cube, and keep the other three cost columns where they already sit. State the choice: allocating by weight instead reorders lanes whenever freight is bulky rather than dense.
  2. Restrict to the set of lanes both carriers actually serve in the window. Comparing over all lanes measures which carrier was assigned the cheap lanes, not which carrier is cheaper.
  3. Resample shipments, not legs. Legs of one load share a single allocated linehaul and a single dispatch decision, so treating them as independent draws understates the variance of the estimate.
  4. Recompute the statistic as a ratio of sums on every resample, total allocated cost over total shipped units. Taking the mean of leg-level cost-per-unit values instead gives a different estimand in which a one-unit leg counts as much as a full truckload.
  5. Report both the raw difference and a lane-standardised difference where lane weights are fixed at the pooled volume share, and say which one you would put in front of a decision maker.

Follow-up

  • The interval crosses zero. What would you need in volume or in window length to resolve a difference of 2 cents per unit?
  • One carrier's accessorials are rising while its linehaul is flat. What is that signature telling you about execution versus rates?
  • How does your interval change if one shipment accounts for 15 percent of the units?

Explain the difference between RANK and DENSE_RANK in a real-world scenario.

Medium · sql and data manipulation

Approach

  1. Check whether any join is one-to-many before aggregating, or the sums inflate.
  2. Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.
  3. Compute rates by summing numerator and denominator separately, never by averaging rates.

Follow-up

  • What breaks if events arrive late or out of order?
  • How does the query change if the join becomes one-to-many?

Write a query using SQL window functions to calculate a moving average of energy consumption over the last 30 days.

Medium · sql and data manipulation

Approach

  1. Compute rates by summing numerator and denominator separately, never by averaging rates.
  2. Say which table is the grain you start from, and join outward from it.
  3. Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.

Follow-up

  • How would you verify this result without re-running the same query?
  • How does the query change if the join becomes one-to-many?

Dead stock cells excluding SKUs used as substitutes

Medium · anti-join · null semantics · dead stock

Find dead stock: sku_id x location_id cells whose latest fct_inventory_daily row has on_hand_qty > 0 and which have no fct_order_line with that sku_id and ship_from_location_id in the last 90 days. Also exclude any SKU that filled another line as a substitute in that window; fct_order_line.substituted_sku_id is NULL on every line that was not substituted. Value each cell at on_hand_qty * standard_cost_cents taken from the snapshot, not from dim_sku. Return the cell, days since its last demand line, and value, ordered by value. Treat line_status = 'cancelled_no_supply' as demand.

Approach

  1. Take the latest snapshot per sku-location with ROW_NUMBER() OVER (PARTITION BY sku_id, location_id ORDER BY inventory_date DESC) = 1, or an equivalent MAX(inventory_date) join, and keep rows with on_hand_qty > 0.
  2. Anti-join demand with NOT EXISTS against fct_order_line on both sku_id and ship_from_location_id over the 90-day window, counting every line status including cancelled_no_supply, because unmet demand is still demand and a cell with it is not dead.
  3. Write the substitute exclusion as NOT EXISTS, or force substituted_sku_id IS NOT NULL inside the subquery. NOT IN over a column that contains NULLs evaluates to NULL for every candidate that is not an explicit match, so the predicate is never true and the result set is empty.
  4. Value from the snapshot's standard_cost_cents rather than dim_sku, since the dimension carries only the cost in force today and is revised at period close without back-dating.
  5. Get days since last demand from a LEFT JOIN LATERAL MAX(ordered_at_utc), and report cells that never had a line in a separate bucket instead of as a very large number.

Worked solution (30 min)

  1. CTE latest_snap: ROW_NUMBER over sku_id, location_id ordered by inventory_date DESC, filtered to rn = 1 and on_hand_qty > 0.
  2. CTE last_demand: MAX(ordered_at_utc) grouped by sku_id, ship_from_location_id over all of fct_order_line, with no status filter.
  3. Select from latest_snap LEFT JOIN last_demand, keeping rows where the max is NULL or older than 90 days.
  4. Add AND NOT EXISTS (SELECT 1 FROM fct_order_line o WHERE o.substituted_sku_id = latest_snap.sku_id AND o.ordered_at_utc >= now() - interval '90 days').
  5. Project value_cents = on_hand_qty * standard_cost_cents, order by it descending, and run the same query once with NOT IN to see the empty result for yourself.

Expected result: One row per dead sku-location cell with value_cents computed from the latest snapshot's own cost column, days_since_last_demand (or an explicit never-ordered bucket), ordered by value_cents descending. The substitute exclusion removes some rows; it must not empty the result.

Verify it yourself

  • Swapping NOT EXISTS for NOT IN on substituted_sku_id collapses the output to zero rows. That is the diagnostic for the NULL semantics, not a data finding.
  • Total value across returned cells is strictly less than total on-hand value at the same snapshot date.
  • No returned cell appears in SELECT DISTINCT sku_id, ship_from_location_id FROM fct_order_line over the same 90 days.

Follow-up

  • The query returns zero rows. Name the two likeliest causes and say which you would test first, with the one-line test.
  • How do you separate genuinely dead stock from a seasonal item out of season and from a lifecycle_status = 'pre_launch' SKU?
  • The same SKU is dead at one node and short at another. Write the query that finds that pattern and say what it implies about the policy.

How would you design a metric to measure the success of a new energy efficiency feature?

Medium · product sense and metrics

Approach

  1. Decompose the metric into the rates that drive it, and say which one you would check first.
  2. Fix the population and the time window before naming any metric.
  3. Restate the decision this analysis has to support, and who acts on the answer.

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 do you prioritize which product features to build based on limited data?

Medium · product sense and metrics

Approach

  1. Name one primary metric, then the guardrail that stops it being gamed.
  2. Decompose the metric into the rates that drive it, and say which one you would check first.
  3. Restate the decision this analysis has to support, and who acts on the answer.

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?

If you noticed a 10% drop in a key product metric overnight, what steps would you take to diagnose the root cause?

Medium · product sense and metrics

Approach

  1. Name one primary metric, then the guardrail that stops it being gamed.
  2. Restate the decision this analysis has to support, and who acts on the answer.
  3. 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?

What are the primary trade-offs when choosing between a short-term and long-term user engagement metric?

Medium · product sense and metrics

Approach

  1. Fix the population and the time window before naming any metric.
  2. Name one primary metric, then the guardrail that stops it being gamed.
  3. Restate the decision this analysis has to support, and who acts on the answer.

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?

Explain the concept of "selection bias" in the context of user-facing experiments.

Medium · a/b testing and experimentation

Approach

  1. Name the randomisation unit first; it decides the variance and what the test can detect.
  2. Decide the analysis before seeing data, including how long it runs and when you look.
  3. State the primary metric and the minimum effect worth shipping, then size the test.

Follow-up

  • What would you conclude if the result is positive but the test is underpowered?
  • What would you do if you could not randomise at all?

What are the most common experimentation pitfalls you have encountered in your previous projects?

Medium · a/b testing and experimentation

Approach

  1. Name the randomisation unit first; it decides the variance and what the test can detect.
  2. State the primary metric and the minimum effect worth shipping, then size the test.
  3. Say whether units interfere with each other, and switch design if they do.

Follow-up

  • What would you do if you could not randomise at all?
  • What would you conclude if the result is positive but the test is underpowered?

Set a stopping rule and error budget for a daily-read test

Medium · peeking · sequential testing · multiple comparisons · alpha spending

A carrier allocation change is randomised at the shipment leg within lane. The primary metric is landed cost per delivered unit from fct_shipment_leg; the team also watches 14 guardrails, including on-time rate, accessorial share and refused legs. The dashboard refreshes daily and the team plans to stop as soon as the primary is significant. The run is planned at 20 business days. Give the type I error of that plan, specify a stopping rule that fixes it, and say how you treat the 14 guardrails.

Approach

  1. Quantify the peeking cost rather than describing it. Testing accumulating data at nominal two-sided 0.05 on each of 20 equally spaced looks carries a type I error of roughly 25%, against the 5% the team believes it is running; the inflation comes from taking the maximum of a correlated sequence of statistics instead of reading one.
  2. Match the correction to the behaviour they actually want. To stop early on a fixed schedule, use a group-sequential plan with an alpha-spending function: at five interim looks the O'Brien-Fleming boundaries are z = 4.56, 3.23, 2.63, 2.28, 2.04, which spends almost nothing early and leaves the final look near full alpha for about 3% more maximum sample; Pocock's constant z = 2.41 stops earlier but pays for it at the end. To look whenever they like with no schedule, use an anytime-valid confidence sequence, which is honest under continuous monitoring but needs more data for the same interval width.
  3. Do not adjust the primary for the guardrails. It is one hypothesis, and its alpha is spent entirely by the stopping rule.
  4. Treat the guardrails by what a miss costs. For the few that would actually block a launch, pre-register non-inferiority margins and test each at unadjusted 0.05, because a Bonferroni here buys a lower false-alarm rate by blinding the guardrail to the regression it exists to catch. Report the rest with Benjamini-Hochberg q-values at FDR 0.1 as triage, and state up front that 14 independent guardrails at 0.05 give a 1 - 0.95^14 = 51% chance of at least one spurious flag.
  5. Cluster the variance to match the dependence: legs on the same lane and day share weather, carrier capacity and fuel shocks, so leg-level iid standard errors are too small and make every boundary easier to cross than the design intends.

Worked solution (30 min)

  1. State the uncorrected error: about 25% at 20 looks, against a believed 5%.
  2. Fix five interim analyses at equal information fractions with an O'Brien-Fleming spending function and boundaries z = 4.56, 3.23, 2.63, 2.28, 2.04.
  3. Re-size for the plan: maximum sample rises about 3% over a fixed-horizon test at the same power, while expected sample falls when a real effect is present.
  4. Write the guardrail policy: three or four blocking guardrails with pre-registered non-inferiority margins at unadjusted 0.05, the remainder Benjamini-Hochberg at FDR 0.1 for triage only.
  5. Fit the primary with standard errors clustered at lane by day and re-check the boundary crossings under the clustered SEs.

Expected result: Daily testing for 20 days at nominal 0.05 runs a type I error near 25%. A five-look O'Brien-Fleming plan restores 5% overall while still permitting an early stop, at about 3% more maximum sample. The 14 guardrails carry a 51% chance of at least one spurious flag at unadjusted 0.05 and are handled with pre-registered blocking margins plus BH at FDR 0.1 for the rest, never by adjusting the primary.

Verify it yourself

  • The final O'Brien-Fleming boundary, 2.04, should sit just above the fixed-horizon 1.96; a plan whose last boundary is far above that is front-loaded and is throwing away power.
  • Simulate the null by replaying the daily rule on 1,000 A/A samples of historical legs: the uncorrected crossing rate should land near 25% and the corrected near 5%.
  • Recompute 1 - 0.95^k for the number of guardrails you actually ship with; at 14 it is 0.51, and the figure should be quoted in the readout rather than assumed.

Follow-up

  • Legs of one shipment share a truck and an allocated cost. Is the leg a legitimate randomisation unit here, and what breaks if it is not?
  • The primary crosses the boundary on day 4. What do you need to see before you recommend stopping, and what would make you keep running anyway?

Unit fill rate fell four points in one region

Easy · fill rate · segment cuts · mix shift

Weekly unit fill rate for one region fell from 96.1 percent to 92.0 percent over four weeks and has not recovered. Network fill rate is flat. You have fct_order_line (ordered_qty, shipped_qty, requested_ship_date, ship_from_location_id, sku_id, line_status, short_reason_code), dim_location (location_type, region_code, echelon) and dim_sku (abc_class, xyz_class, lifecycle_status). Produce the first four query cuts, say what each one rules in or out, and name the single most likely cause together with the evidence that would confirm it. Thirty minutes, SQL plus a short written argument.

Approach

  1. Rebuild the metric by summing shipped_qty and ordered_qty to region level and dividing once, rather than averaging per-SKU-location rates. An unweighted mean of cell rates moves with portfolio mix on its own, so if the drop does not survive re-summing there is nothing physical to diagnose.
  2. Cut by ship_from_location_id first. If one node carries the whole drop the mix of demand across nodes is not the story and the problem is local; if every node fell a little, the cause sits upstream in supply or forecast rather than in any warehouse.
  3. Decompose the region change over abc_class by xyz_class cells into within-cell, mix and interaction terms: delta R = SUM(w0 * (r1 - r0)) + SUM(r0 * (w1 - w0)) + SUM((w1 - w0) * (r1 - r0)), where w is a cell's share of the denominator and r is its rate. A dominant mix term means demand moved toward hard-to-serve intermittent items and no cell actually got worse.
  4. Group the lost units (ordered_qty minus shipped_qty) by short_reason_code. 'no_stock' points at planning, 'pick_shortage' and 'damage_on_pick' mean the stock was physically present and execution lost it, 'allocation_rule' means the units existed and were promised to someone else, and 'credit_hold' is not a supply chain failure at all.
  5. Only then cross the weekly series against the promotion calendar, against SKUs with lifecycle_status = 'pre_launch' cutting in, and against accounts placing their first order in the window. A step change starting in the same week as a promotion or a new-item onboarding is a demand-side event, not a degradation.

Follow-up

  • Fill rate is flat nationally but down in this region. What does that tell you about where the stock went, and how would you test it?
  • Most of the failed units carry short_reason_code = 'no_stock', yet on_hand_qty at the node stayed above reorder_point_qty all month. How is that possible?
  • Would you publish this rate weighted by units or by revenue, and which team gets a different answer from each?

Suggested practice checklist

Four days spend equal time on query work, statistics, modelling and product judgement at deliberately shallow depth, which produces a scored map of where you actually stand. The last three days spend everything on the two areas the role weights most, and close by re-running day one to measure movement.

Day 1 — Breadth pass: query fluency

  • Solve six prompts spanning aggregation, joins, window functions and date arithmetic in 60 minutes total, stopping at 10 minutes each whether or not it works, and mark every prompt as solved, solved slowly, or stuck.
  • For each unsolved prompt write the single blocking sentence (I lost the grain, I did not know the frame clause, I could not express the date boundary) instead of reading the solution.
  • Translate one pandas transformation you know well into SQL and one SQL query into pandas, checking that both return the same row count and the same totals.

Deliverable: A scored six-row table, one line per prompt, saved for the day-seven re-run.

Day 2 — Breadth pass: statistics and inference

  • Answer ten short questions in writing with nothing open: what a p-value is conditional on, what a 95 percent interval covers across repeated samples, when a paired test is the right one, what the bootstrap estimates, why multiple comparisons inflate false positives, how controlling the family-wise error rate differs from controlling the false discovery rate, what power depends on, what a missed real effect costs a product, the three situations where the central limit theorem does not rescue you (small n, very heavy tails, dependent observations), and what a standard error is the standard deviation of.
  • Grade yourself against a reference and count only the answers that were exactly right, not the ones that were nearly right.
  • Rewrite the two weakest answers the following morning from memory in full sentences.

Deliverable: Ten graded answers with an honest count of exact hits.

Day 3 — Breadth pass: modelling

  • Take one tabular dataset end to end in 90 minutes: a leakage-safe split, a baseline that is not a model (majority class or historical mean), one regularized linear model, one gradient-boosted tree, and a single evaluation metric chosen before you look at any result.
  • Write why that metric fits the cost structure: precision at a fixed recall for alerting, calibration for anything feeding a price or a threshold, ranking metrics for retrieval, and note that area under the ROC curve is insensitive to class balance in a way that can flatter a rare-positive problem.
  • Name the leak you were most likely to introduce (an encoding fit on all rows before splitting, or a feature computed after the label's timestamp) and write the check that would have caught it.

Deliverable: A notebook whose first cell states the metric and the baseline, plus two lines on what beat what and by how much.

Day 4 — Breadth pass: product judgement

  • Answer three case prompts aloud at 15 minutes each, timing how long passes before you state a success metric.
  • For one case write the first segmentation you would run and the row counts you expect per segment, so that a tiny segment cannot quietly drive the conclusion.
  • Take a metric definition you did not write, from a public dashboard, a textbook, or documentation you already have open, and list every place two analysts implementing it would diverge: which rows the denominator admits, whether the unit is an account or a person, what the time window is anchored to, and what happens to data that arrives late. Then write the one question that would close the largest of those gaps.

Deliverable: Three recorded case answers plus an ambiguity list for a metric someone else defined, ending in the single question you would ask about it.

Day 5 — Depth, first area

  • Rank the four areas by how many bullet points in the role description each one covers, pick the top one, and spend the entire day inside it.
  • Work the six hardest problems you can find in that area and for each write the generalizable move you should have reached for first, rather than the answer.
  • Re-solve the two you failed the same evening with notes closed.

Deliverable: Six generalizable moves written as instructions to yourself, not as solutions.

Day 6 — Depth, second area, and the seam between them

  • Repeat the depth protocol on the second-ranked area with the same six-problem structure.
  • Construct one problem that requires both areas at once, for example a metric redefinition whose effect you must validate with a test whose readout you then have to query.
  • Solve your own combined problem end to end and note where the handoff between the two areas cost you time.

Deliverable: One combined problem, solved end to end, with the handoff failure written down.

Day 7 — Integration and re-measurement

  • Re-run the six prompts from day one under the same clock and compare both correctness and time.
  • Run a 60-minute mixed mock that moves between areas without warning, since switching cost is what breadth passes do not train.
  • Write the two areas you would still fail on, and the sentence you will use in the interview when you hit one of them.

Deliverable: A before-and-after score table plus a written plan for the two remaining gaps.

Ownership when the result is inconvenient

Sometimes the honest read is that the initiative did not work, and the person who commissioned the analysis was hoping otherwise. Interviewers want to know whether you softened it. Prepare the case where you delivered an unwelcome result, how you presented the uncertainty without hiding behind it, and what the team did next.

How do you handle a disagreement with a product manager regarding the interpretation of a specific metric?

Medium · behavioural and stakeholder questions

Approach

  1. Close with what you would do differently, concretely.
  2. Pick a story where you drove the decision, not one where you observed it.
  3. Quantify the outcome, including what you would not claim credit for.

Follow-up

  • What did you decide not to do, and why?
  • What would you do differently if you ran that project again?

Prioritise transport, plant and commercial in one week

Medium · prioritisation · stakeholder management · decision value

Three requests land in the same week. Transport wants landed cost per delivered unit split by lane and mode from fct_shipment_leg for a carrier bid that closes in nine days. A plant manager wants OEE on two work centres decomposed into availability, performance and quality from fct_production_run for a capital request due next month. Commercial wants a fill-rate root cause from fct_order_line for an account review on Thursday. You are the only data scientist and have about four working days. Give your order, the rule that produced it, and what you say to the two who wait.

Approach

  1. Rank by the decision each request feeds and by whether your input can still change it, not by seniority or by who asked loudest: a bid closing in nine days is a live decision with a large irreversible spend attached, a capital request due next month has slack, and an account review has a fixed date but a smaller reversible decision.
  2. Check reversibility and blast radius: carrier rates lock for a contract period across every lane, so an error or an absence there is expensive for a year, while the fill-rate story can be revised next week.
  3. Look for the cheap partial that unblocks someone else: the fill-rate cut by node, by short_reason_code and by week is a few hours of work and covers most of what commercial needs on Thursday, so it does not have to wait behind the bid.
  4. Sequence with explicit time boxes: the commercial cut first because it is short and date-locked, the lane and mode cost analysis next with the allocation basis for multi-stop loads stated up front, and the OEE decomposition scheduled into the following week with a date the plant manager can hold you to.
  5. Tell the plant manager directly and early, with a date rather than a maybe, and say what you need from him in the meantime so the delay produces something.
  6. Escalate the trade-off rather than absorbing it silently: your manager should know a capital request slipped a week, because that is a business choice and not yours alone to make.

Follow-up

  • The plant manager escalates and his director asks you to reorder. What do you do?
  • Which of the three would you push back on entirely, and what would you offer instead?

Defend a finding that the expedite program bought nothing

Medium · defending findings · counterfactual reasoning · landed cost

Over two quarters, expedite_premium_cents on outbound legs in fct_shipment_leg rose from 0.4 to 1.3 percent of landed cost, while perfect order rate moved from 91.2 to 91.5 percent, inside the week-to-week spread. The transport lead who sponsored the expedite program disputes the finding in a review in front of his director, arguing that your window contains a port disruption that would have made service worse without the spend. Present the finding, say what you concede on the spot, say what you hold, and name the evidence that would change your conclusion.

Approach

  1. Restate his objection in its strongest form before answering it, because a counterfactual worsening is a legitimate argument and treating it as an excuse ends the conversation.
  2. Separate what you measured from what you claimed: the data show no detectable service gain, not that expedite has no effect, and the difference is the entire argument.
  3. Test his hypothesis with the data you already have rather than defending in the abstract: split legs by exception_code = 'customs_hold' and by lane, and compare expedited against non-expedited legs on the same lanes in the same weeks, since if expedite were holding the line the expedited lanes should show a service gap over comparable non-expedited ones.
  4. Concede what is true: without a holdout you cannot rule out a protective effect, and the pre-period is contaminated by the disruption, so the honest statement is an upper bound on the gain rather than a zero.
  5. Hold the part that survives: the spend is real, it is concentrated in a small set of lanes, and nobody set a decision rule for when a leg gets expedited, which is a controllable problem independent of the counterfactual.
  6. Name the next measurement: a lane-level staggered switch-off with a stated burn-in, and say what it would cost and how long it would take.

Follow-up

  • He offers to run the switch-off only on his two best lanes. Why is that a problem, and what do you counter with?
  • His director asks you for a yes or no on cutting the budget today. What do you say?