As a Data Scientist at Pocket Gems, you play a pivotal role in leveraging data to drive decision-making processes and optimize user experiences across various gaming products. Your insights help shape product development, enhance player engagement, and ultimately contribute to the company's success in a highly competitive landscape. The impact of your work is profound, influencing everything from gameplay mechanics to monetization strategies, thereby directly affecting player satisfaction and business performance.
In this dynamic environment, you will engage with complex datasets and utilize advanced analytical techniques to uncover trends and patterns that inform strategic initiatives. This role is particularly interesting due to the scale of data generated by Pocket Gems' diverse portfolio of games, where your ability to derive actionable insights can lead to innovative features and improvements. You will work closely with cross-functional teams, including product managers and engineers, to ensure that data-driven decisions are at the forefront of game development.
Phone Screen
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
Take-Home Assessment
reportedThe clock is part of the test. Three to six hours is not enough to do everything the dataset supports, so the submission mostly reveals how you spend a fixed budget against an open question. A reviewer sees which paths you took and, by absence, which you abandoned. Work that runs out of time inside the analysis ships a thin conclusion, while work that cuts scope early protects the last hour for writing. The most reliable way to lose here is to leave the scoping decision implicit, so it reads as something you missed rather than something you chose.
What to demonstrate
- Whether the scope you settled on is presented as a decision with a reason, rather than left for the reader to infer from what is missing
- Whether the depth of the work is consistent with the stated time budget, instead of several half-finished directions left open
- Whether the closing section reads as something written on purpose rather than assembled from whichever cells survived
How to prepare
- Run a timed rehearsal on a public dataset with a hard stop, holding the final sixty minutes for writing no matter where the analysis has got to
- Before opening the data, list the questions it could plausibly answer, pick one, and keep the discarded ones as a short note on what you did not attempt and why
- Commit a one-line finding after each analysis step so the writeup is assembled from recorded results rather than from memory at midnight
Onsite Interview
reportedA loop is not scored one interview at a time. The people you meet compare notes afterwards, usually in a meeting you are not in, and the outcome turns on what each of them can say about you when asked. That rewards something other than survival: every room needs one specific thing worth repeating, and none of them can contradict another. The common way to lose is to tell the same project four times with different numbers in it, or to be uniformly fine in a way that leaves nobody with anything to argue for.
What to demonstrate
- Whether your account of a project survives being told twice, with the same scale, the same metric definition and the same numbers each time
- Whether each interviewer leaves with one concrete claim they could make on your behalf later, rather than an absence of complaints
- Whether a question you already answered in an earlier room gets the same answer at the same depth, without visible impatience
How to prepare
- Write a one-page fact sheet for your two or three main projects that fixes the numbers you will quote: rows of data, the metric as a single sentence, the effect you measured and how long the work took. Say them aloud from the sheet until they come out identical every time
- For each kind of room you expect, decide the one sentence you want that interviewer repeating in a debrief, then check during the mock that you said it outright instead of implying it
- Rehearse answering the same project question twice in one sitting, the second time as though you had not just answered it, because the thing that needs fixing is the flatness that creeps into a repeated story
PracHub editorial advice for the preparation topics above.
Randomising players individually for a change that acts on a shared pool.
Matchmaking parameters, queue populations, tradeable-item supply and event leaderboards are shared resources: a treated player is matched against a control player, and treated supply lands in the control arm's market. The treatment leaks across arms, so the measured difference understates or reverses the true effect, and the control arm is no longer a clean counterfactual. Cluster by region and mode, or switchback on time slices with a burn-in long enough to clear carryover in the shared state.
Treating the account as the person, and the calendar week as neutral time.
Reinstalls, multi-platform play and shared accounts split or merge humans relative to player_id, which inflates install counts and deflates retention denominators in ways that correlate with platform and campaign. Meanwhile daily actives spike on release day and decay over the following week, so a week-over-week read aliases the content calendar. Anchor comparisons to time since release or to matched days in the release cycle, and report identity-sensitive metrics with an explicit statement of which identity key was used.
Explaining an aggregate move without decomposing the mix shift
Split the change in the aggregate into within-segment movement and movement in segment weights before you explain it. Every segment's rate can fall while the overall rate rises, purely because volume shifted toward segments that already had higher rates.
Analysing at a different unit than the one randomised
Say out loud what was randomised (user, device, account, cluster) and make the analysis unit match, or account for the clustering with cluster-robust standard errors, the delta method, or aggregation up to the randomised unit. Randomising users and then running a test over sessions understates variance and inflates the false-positive rate.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Write a function to calculate the Pearson correlation coefficient.
Write a function to calculate the Pearson correlation coefficient.
Approach
- Sanity-check the answer against a simple bound or a simulated case.
- Quantify uncertainty explicitly rather than reporting a point estimate alone.
- Translate the result into the decision it informs, in one plain sentence.
Follow-up
- What sample size would you need to detect an effect half this size?
- Which assumption here is most likely to be violated in practice?
How do you evaluate the performance of a machine learning model?
How do you evaluate the performance of a machine learning 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
- Where could label leakage enter this setup?
- What would you monitor after launch to know the model is still valid?
Given a dataset, how would you implement a decision tree classifier?
Given a dataset, how would you implement a decision tree classifier?
Approach
- Pick an evaluation metric that matches the cost of each error type, not a default.
- Frame the prediction: the label, the moment of prediction, and the action it triggers.
- Say how the offline result would be validated online before it is trusted.
Follow-up
- Where could label leakage enter this setup?
- What would you monitor after launch to know the model is still valid?
Discrete hazard of churn indexed by matches played
Given matches (player_id, started_at) for one install cohort, sessions (player_id, session_start_ts), and a data cutoff timestamp, define churn at match k as no session starting in (t_k, t_k + 14 days], where t_k is the start of that player's k-th match. Build the discrete hazard h(k) and the survival curve S(k) for k = 1 to 50. A player-index enters the risk set at k only if the player has not already churned before k and t_k is at or before cutoff minus 14 days. Return k, risk_set, churned, h and S, and name the two largest hazard spikes.
Approach
- Build the match index yourself: sort matches by (player_id, started_at) and set k = groupby('player_id').cumcount() + 1. Never take a stored index without verifying it is dense per player, because one gap shifts every downstream k for that player.
- Decide churn per (player, k) without a cross join. Sort each player's session timestamps once and use np.searchsorted to ask whether any session falls in the half-open window (t_k, t_k + 14d]. A merge of matches to sessions is quadratic in the busiest players and is where this exercise usually dies.
- Keep observability separate from the event. A player-index is usable at k only when t_k is at or before cutoff minus 14 days; a player whose 30th match was yesterday contributes to k = 1 through 29 and then leaves. This is right-censoring on the match axis, and dropping those players outright instead of truncating them biases the entire curve toward whoever plays fastest.
- Compute h(k) = churned_at_k / risk_set_k and S(k) as the cumulative product of (1 - h(j)) for j up to k. The product form is what makes the censoring handling count; a naive share of the original cohort still alive divides by a denominator containing players who could never have been observed at k.
- Read the spikes against the loop rather than the calendar: a bump at a given k usually maps to a difficulty wall, the end of a tutorial reward track, or the point where a faucet stops paying. Name the k values, then name the query that would confirm each one, rather than asserting a cause.
Worked solution 40 min
- Derive t_k per player by sorting and using cumcount, then truncate each player's indices at the last k satisfying t_k at or before cutoff minus 14 days.
- For each surviving (player, k), use a per-player searchsorted over session timestamps to decide whether a session falls in the 14-day window, and take each player's first churn index as their exit.
- Aggregate risk_set and churned counts by k for k = 1 to 50, then compute h(k) and the cumulative-product S(k).
- Rank h(k) and report the two largest, with the k values and the local shape around them.
Follow-up
- Someone reports that players who reach match 50 retain four times better. Rewrite that as a claim you would be willing to defend, and say what it costs you to do so.
- Your definition retires a player who keeps logging in but stops playing matches. Is that churn? What does including or excluding them do to the curve?
- Add a time-varying covariate for whether the player was in a party at match k. What changes about the estimator, and what can you now claim that you could not before?
Report per-SKU net revenue alongside granted premium currency
fct_iap_transaction has transaction_id, player_id, sku_id, purchase_ts, price_usd_net, status. fct_currency_ledger has transaction_id (nullable), currency_code, delta_amount, source_system. A single completed purchase can produce several ledger rows with source_system = 'iap_grant': the base pack, a first-purchase bonus and an event bonus are separate entries. For last month's completed transactions, return per sku_id the transaction count, net USD revenue and total premium currency granted. Write it so the revenue figure is not inflated by the grant rows.
Approach
- State the grain of each side before writing any join. fct_iap_transaction is one row per transaction; the iap_grant rows are one-to-many against it. Joining them directly produces a result at grant grain, where any SUM of price_usd_net counts each purchase once per grant row.
- Pre-aggregate the ledger to transaction grain in a CTE: SUM(delta_amount) FILTER (WHERE currency_code = 'premium') grouped by transaction_id, restricted to source_system = 'iap_grant'. The CTE is now one row per transaction and the join becomes many-to-one.
- Left join that CTE onto the filtered transactions so a completed purchase that produced no grant row still appears with a NULL grant total. That combination is a fulfilment bug worth surfacing, not hiding behind an inner join.
- Filter transactions on status = 'completed' and purchase_ts inside last month. Because this table mutates in place, a transaction later refunded now carries status = 'refunded' and is already excluded; say that out loud rather than adding a redundant refund subtraction that would double-count the adjustment.
- Aggregate to sku_id and add a count of transactions with no matching grant, so the fulfilment gap is legible in the same output instead of needing a second query.
Follow-up
- How would you prove the fan-out was really happening, using only row counts and no prior knowledge of the data?
- Last month's transactions have not finished refunding. At what cohort age would you publish this table, and what do you show a stakeholder in the meantime?
- A currency_pack SKU shows net revenue but zero granted premium currency. Walk me through the next three queries you run.
Stitch crash-fragmented sessions into play blocks with gaps and islands
fct_session has session_id, player_id, session_start_ts, session_end_ts (NULL when the client crashed), duration_seconds (NULL alongside it), platform and ended_reason. A crash splits one sitting into two rows seconds apart. Group consecutive sessions for the same player and platform into play blocks, starting a new block when the gap from the previous end to the next start is 120 seconds or more. For NULL ends, impute session_start_ts plus that player's median duration_seconds on the same platform. Return one row per block.
Approach
- Build the imputed end in its own CTE: COALESCE(session_end_ts, session_start_ts + the median duration as an interval). Compute the median with PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY duration_seconds) grouped by player_id and platform over the non-NULL rows, then join it back. Players with no non-NULL session have no median, so decide explicitly whether to drop them and report how many.
- Get the previous end with LAG(imputed_end) OVER (PARTITION BY player_id, platform ORDER BY session_start_ts, session_id). The session_id tiebreak matters because two sessions can share a start timestamp on a device that relaunched instantly.
- Flag a block boundary where prev_end IS NULL (the first session in the partition) OR session_start_ts - prev_end >= interval '120 seconds', and cast that flag to an integer.
- Turn flags into block ids with SUM(flag) OVER (PARTITION BY player_id, platform ORDER BY session_start_ts, session_id ROWS UNBOUNDED PRECEDING). This is the gaps-and-islands step. The ROWS frame here is explicit, not load-bearing: session_id is unique, so every row is its own peer group and the default RANGE frame would produce the same block ids. What actually keeps two sittings apart is the session_id tiebreak, which is why it has to appear in all three window clauses.
- Drop that tiebreak and the ordering stops being total, which breaks the step in one of two ways depending on the frame. Under the default RANGE, sessions sharing a start timestamp are peers, so each receives the tie group's closing cumulative total, they share a block id, and two genuinely separate sittings merge. Under ROWS they get distinct ids, but the order inside the tie is unspecified, so which session opens the block, and the LAG that fed the boundary flag, can differ between runs on identical data.
- Aggregate by (player_id, platform, block_id) for MIN(session_start_ts), MAX(imputed_end), COUNT(*), the summed in-session seconds and BOOL_OR(ended_reason = 'crash') to mark blocks stitched across a crash.
- State the direction of the imputation bias: if the imputed end lands earlier than the true end, the gap is overstated and the query under-stitches, so the crash-stitch rate under this rule is a lower bound.
Worked solution 35 min
- Compute per-(player_id, platform) median duration_seconds over rows where it is NOT NULL, and count how many players have no median at all.
- Build the imputed_end CTE and confirm no NULL ends remain among the rows you kept.
- Add LAG, the boundary flag and the cumulative-sum block id in one CTE, all three carrying the same PARTITION BY (player_id, platform) and the same ORDER BY (session_start_ts, session_id). If the three orderings disagree, the flags and the ids are computed over different sequences and the block boundaries land on the wrong rows.
- Aggregate to block grain and spot-check a player known to have crashed: their two adjacent rows should share one block id.
- Recompute with the threshold at 30 and at 600 seconds and watch the block count move. A threshold that changes nothing means crashes are not in fact producing adjacent rows.
Follow-up
- The 120-second threshold is an assertion. How would you pick it from the distribution of inter-session gaps instead?
- Under your imputation, does the block count over-count or under-count real sittings, and which direction would you rather err in for a crash-impact readout?
- A player is on two platforms at once. Should that be one block or two, and what does your partition key currently decide for you?
If tasked with increasing player retention, what data would you analyz…
If tasked with increasing player retention, what data would you analyze?
Approach
- Decompose the metric into the rates that drive it, and say which one you would check first.
- Name one primary metric, then the guardrail that stops it being gamed.
- 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?
- How would you detect that the metric is being gamed rather than genuinely improving?
Given a dataset, how would you identify and handle outliers?
Given a dataset, how would you identify and handle outliers?
Approach
- Decompose the metric into the rates that drive it, and say which one you would check first.
- State what result would change your recommendation, so the answer is falsifiable.
- Fix the population and the time window before naming any metric.
Follow-up
- What would you do if the primary metric and the guardrail moved in opposite directions?
- How would you detect that the metric is being gamed rather than genuinely improving?
How do you prioritize your tasks when working under tight deadlines?
How do you prioritize your tasks when working under tight deadlines?
Approach
- Restate the decision this analysis has to support, and who acts on the answer.
- Decompose the metric into the rates that drive it, and say which one you would check first.
- Name one primary metric, then the guardrail that stops it being gamed.
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?
Describe how you would design an A/B test for a new game feature.
Describe how you would design an A/B test for a new game feature.
Approach
- Name the guardrails that would stop a launch even on a positive primary result.
- State the primary metric and the minimum effect worth shipping, then size the test.
- Decide the analysis before seeing data, including how long it runs and when you look.
Follow-up
- How would you handle interference between treated and control units?
- What would you do if you could not randomise at all?
Discuss a complex data pipeline you have built and the challenges face…
Discuss a complex data pipeline you have built and the challenges faced.
Approach
- Clarify what is being asked and what a complete answer would contain.
- Work from the decision backwards to the evidence you would need.
- Say what you would check first and why it is the highest-information step.
Follow-up
- How would you know your answer was wrong?
- What assumption would you test first?
Build the scorecard for a season pass without overstating young cohorts
A season pass (item_class = 'battle_pass') sells for real money and pays premium currency back across its tiers. Two weeks after launch, a deck reports gross bookings per install for the launch-week cohort against last quarter's cohort and claims a 40% lift. Using fct_iap_transaction (price_usd_gross, platform_fee_usd, price_usd_net, status, refund_ts, purchase_ts), fct_currency_ledger and dim_player, rewrite the scorecard: give the primary metric with its maturity rule, two guardrails, and the reason the reported lift is not evidence.
Approach
- Kill the comparison first. A two-week-old cohort has two weeks of purchases and almost no refund exposure, while last quarter's cohort has a full quarter of both. Gross bookings also ignores platform_fee_usd, which is a percentage haircut that differs by store_channel. The two numbers are not one quantity measured twice, so their ratio means nothing.
- Primary: net revenue per install at a fixed cohort age of 90 days, computed only for install cohorts that have reached that age. Fixing the age fixes refund exposure as well: a reversed purchase leaves status = 'completed' whenever the reversal lands, so a cohort's net revenue keeps falling for weeks after purchase and only equal-age reads compare equal amounts of that decay. The launch cohort has no primary number yet, and saying so plainly is the answer rather than a dodge.
- Give the team something honest to read at two weeks: net revenue per install at 14 days of cohort age, compared only against the 14-day value of earlier cohorts. Fixed-age against fixed-age, never as-of-today against as-of-today.
- Guardrail one: refund and chargeback rate at 60-day maturity on pass purchases, restricted to purchase-date cohorts at least 60 days old. This is precisely the exposure the two-week read is structurally blind to.
- Guardrail two: premium-currency faucet volume with source_system = 'pass_tier', reported next to the premium sink-to-faucet ratio. A pass that pays back most of its price in currency is partly a discount on future purchases, and that cost lands in the economy rather than on the pass's own revenue line.
- Decompose so any movement is attributable: net revenue per install equals paying conversion multiplied by net revenue per payer. State which factor moved before recommending anything, because the two imply opposite follow-ups.
Worked solution 30 min
- Write the net revenue definition once, in full: sum of price_usd_net over rows with purchase_ts inside the cohort window and status = 'completed'. There is no second refund term. status is current state, so a reversed purchase has already left that filter, and subtracting it as well deducts the refund twice. If your warehouse instead freezes status at purchase time, the reversal term keyed on refund_ts is required, so confirm which column carries the current state before writing the SQL.
- Write the maturity rule: fixed cohort age, with younger cohorts excluded rather than extrapolated or annualised.
- Build the fixed-age comparison table, every cohort at 14, 60 and 90 days, so a young cohort shows a blank cell rather than a misleading one.
- Add both guardrails with their windows and their cohort restrictions.
- Write the decomposition identity and the rule for which factor you report first.
Follow-up
- The pass pays back 900 premium currency against a 1,000-currency equivalent price. What does that do to next quarter's currency-pack revenue, and which metric in your scorecard would show it first?
- Last quarter's cohort is now 100 days old. Which of its numbers can you compare against the launch cohort today, and which cannot be compared at all?
Abandon rate spiked with a regional incident and a flag change
Match abandon rate, defined as rows with result = 'abandon' or disconnected = true over all rows with started_at in the window, rose from 4.1% to 7.8% in a week. Two things happened: a two-day server incident in one region, and a client release on one platform. fct_match_participant carries match_id, player_id, started_at, result, disconnected, server_region, game_mode; fct_session carries player_id, session_start_ts, platform, app_version. Attribute the 3.7-point rise across both causes and a residual.
Approach
- Split the numerator into its two disjoint terms before any segmentation: rows with result='abandon', and rows with disconnected=true and result <> 'abandon'. The metric is an OR of two signals that can move independently, and a change in flag semantics moves only one of them while a genuine outage moves both.
- Isolate the regional incident with a two-dimensional cut of server_region by day. A real incident is bounded in both dimensions: it appears in one region, on the days the incident ran, and disappears afterwards. Compute its contribution as the region's share of weekly matches times its abandon-rate delta times the fraction of the week affected.
- Isolate the client change by joining participants to sessions on player and time to attach platform and app_version, then cutting by version. A logging or semantics change produces a step at the version boundary and a weekly aggregate that tracks the version adoption curve, not the calendar. Compute its contribution as the platform's share of matches times the new version's share of that platform's matches times the rate delta on the new version.
- Discriminate the flag change from a real disconnect problem using corroborating signals that a semantics change would not move: fct_session ended_reason='crash' rate on the new version, matchmaking wait, and the result='abandon' term on its own. If only the disconnected flag moved, the flag's meaning changed.
- Add the two contributions and report the residual explicitly. A residual that is small relative to the two named terms is the honest end of the analysis; a large one means a third cause is present and should be named as unexplained rather than absorbed into either story.
- Recommend the metric repair: report the result='abandon' term separately so the series stays comparable across client versions, and either backfill a version-consistent disconnected definition or mark the discontinuity on every chart built on it.
Follow-up
- The two causes overlapped in time. How do you keep them from stealing each other's attribution, and what does the interaction term look like?
- If the residual were 1.5 points instead of 0.3, what would you look at next?
- How do you decide whether to restate the historical series or to annotate the break, and who needs to agree?
Roughly 90 minutes a night on weekdays with one longer weekend block. The plan deliberately cuts scope rather than compressing everything, on the assumption that finishing one thing a night beats half-starting four.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Fix the scope and set a baseline
- Read the role description and write the three things the loop will almost certainly test, then write an explicit not-doing list for everything else and keep it visible all week.
- Take one 20-minute SQL prompt and one 10-minute metric question cold, and write the single sentence that says what blocked each attempt, since that sentence is what decides which two topics get the most evenings.
- Set the week's one rule: one problem finished to completion every night, including the night you only have 40 minutes.
Deliverable: A one-page scope with an explicit not-doing list and two cold attempts, each carrying one sentence on what blocked it.
Practice prompt ↗Practice prompt ↗Practice prompt ↗Worked solution ↗02One query pattern, written three times
- Choose the single pattern most likely to appear (a cohort retention grid, or a funnel counted by user) and write it three times from a blank file rather than editing the previous attempt.
- On the third attempt, write the grain of every CTE as a comment before writing its body.
- Stop at 90 minutes even if the third version is imperfect, and write the one thing you would fix with another hour.
Deliverable: Three independent versions of the same query plus a note on what changed between them.
Practice prompt ↗Practice prompt ↗Practice prompt ↗03Only the statistics you will be asked to defend
- Write, in under 200 words, how you would decide whether a difference between two groups is real: the test, its assumptions, and what you would switch to when an assumption fails.
- Compute a 95 percent confidence interval for a difference in proportions by hand on realistic numbers, then write in one sentence what changes if the two samples are paired rather than independent.
- Write your answer to "what does a p-value mean", check it against a definition, and delete the version that describes it as the probability the hypothesis is true.
Deliverable: A 200-word written answer and one hand-computed interval you can reproduce under pressure.
Practice prompt ↗Practice prompt ↗04One case, and the assumptions holding it up
- Answer one product case aloud in 20 minutes with a recording running, then listen back with a pen and mark every claim you asserted without saying what it rested on: an assumed user behaviour, an assumed data source, an assumed baseline rate, an assumed grain.
- Pick the three assumptions the recommendation actually depends on, write how you would check each one against data, and say which one being wrong would flip the recommendation rather than merely weaken it.
- Write the four-step structure you used onto a card small enough to hold in working memory when you are nervous.
Deliverable: One recording, three load-bearing assumptions each with a written check, and a four-step structure card.
Practice prompt ↗Practice prompt ↗Worked solution ↗05Your own work, timed
- Write a 90-second version and a four-minute version of your main project, and time both out loud rather than reading them.
- Prepare answers to the two follow-ups that always come: what you would do differently, and how you knew it worked.
- Put one number in the first sentence and be able to say exactly where that number came from and what it excludes.
Deliverable: Two timed narratives with one defensible number in the opening line.
Practice prompt ↗Practice prompt ↗06The one full rehearsal, in a longer weekend block
- Run a 60-minute mock covering query work, a case and a behavioural question in a single sitting with no breaks, because sustained attention is the thing evenings have not trained.
- Immediately afterwards, and before hearing any feedback, write the three moments you lost the thread.
- Spend the rest of the block only on those three moments, and on nothing you merely feel shaky about.
Deliverable: Mock notes naming three failure moments with a specific fix written under each.
Practice prompt ↗Practice prompt ↗07Taper
- Write the 20-minute warm-up you will actually do on the morning of the interview: one query you can already write from a blank file, one metric you can define out loud, and nothing you have never seen before.
- Re-read only your own notes from this week, and open no new material.
- Write down the logistics: the tool you will be asked to work in, whether lookups are allowed, and the sentence you will use when you do not know something.
Deliverable: A one-page card holding the case structure, the project numbers, and the logistics.
Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
Have two ready. In one, the data was on your side and you had to move someone who outranked you. In the other, the pushback was correct and you changed position. The second is the harder story and it lands better, because it shows you separate being right from being attached to an answer. Name the person's actual objection.
Describe a situation where you had to influence a decision based on yo…
Describe a situation where you had to influence a decision based on your analysis.
Approach
- State the situation in two sentences and spend the rest on your reasoning.
- Name the disagreement or constraint, and how you resolved it with evidence.
- Close with what you would do differently, concretely.
Follow-up
- How did you know the outcome was caused by your change?
- What would you do differently if you ran that project again?
Defend an unpopular readout on a live-ops event
A two-week live-ops event closed with gross bookings up 18% against the prior week. Your readout says it added no net revenue: summed price_usd_net in fct_iap_transaction over the 28 days spanning the event is flat against a matched window one release cycle earlier, and fct_currency_ledger shows premium-currency sinks falling while faucets from source_system = 'pass_tier' rose. The event owner disputes the readout in a review with their director present. Give the argument you would make in that room, and name the one piece of evidence you would concede.
Approach
- Separate the disputed claim from yours. Gross bookings up 18% is true and you are not contesting it. Restate your finding precisely: net of platform fee and of refunds recognised to date, over a window long enough to contain the pull-forward, the number does not move.
- Present the decomposition rather than the aggregate, because the aggregate is what the room is already arguing about. Split the delta into active player-days, paying conversion, and net spend per converting player-day. If conversion is flat and spend per payer spiked inside the event window then fell below baseline after, that is re-timing, not new demand.
- Evidence the re-timing at player grain: take the player_ids who purchased during the event and chart their purchase timing in the four weeks before and after. A pulled-forward purchase shows as a deficit on the same accounts, not as a smaller cohort.
- Bring the ledger in as the second, independent signal. Premium sinks fell while pass_tier faucets rose, so granted currency was banked rather than spent. Report the sink-to-faucet ratio per currency and the balance percentile curve, and exclude is_reversal rows and cs_grant so a correction cannot masquerade as a faucet.
- State the limit of the design out loud before the owner does. There was no holdout, and a matched window still aliases the release calendar. Say which part of your conclusion is robust to that and which is not.
- Close on a decision and a fix: run the next instance with a region-clustered holdout or a staggered start, so the argument is settled by design rather than by seniority.
Follow-up
- The event owner says the banked currency will be spent next month, so the sink drop is timing too. How would you test that claim rather than argue about it?
- If you could add exactly one instrumentation change before the next event, what would it be and what question does it close?
- What would you have said if the net number had been up 3% with an interval spanning zero?
Report a contaminated switchback when the ship call is Friday
A switchback test of a container drop-rate change ran Monday to Sunday on 12-hour slices, randomising the whole region-mode population per slice. On Wednesday a limited-time event went live to everyone, changing both the currency faucet and store traffic for the remaining slices. Treatment and control slices are no longer exchangeable. The change is scheduled to ship Friday and the director wants a number. Give what you say, what you can still salvage from the data, and what you ask for.
Approach
- Say the full-week estimate is unusable before saying anything else, and give the reason in one sentence a non-analyst can repeat: the world changed halfway through, so the two halves of the test measure different games and pooling them averages across that difference.
- Test salvageability rather than assuming it away. If slice assignment is balanced within the pre-event window and that window holds enough slices for a usable standard error, you have a shorter and noisier but uncontaminated estimate. Report it with the widened interval and an explicit statement of the power you lost. Do not pool across the event boundary, and do not run the post-event slices as a second test with the event as a covariate, because the event was not randomised.
- Check carryover independently of contamination, because they fail for different reasons. A drop-rate change leaves players holding containers and currency, so treatment effects persist into the following control slice unless the burn-in exceeds the time it takes a typical player to open what they received. State the burn-in you used and what evidence supports it.
- Give the decision a path rather than a blocker. Offer a cluster-randomised staged rollout by region and mode with the guardrail set pre-registered before launch, which gets the change shipped on Friday while still producing a clean estimate.
- Fix the cause, not the instance. The live-ops calendar was a discovery here and should be a design input, checked against the planned slice schedule before a test is launched.
- Decide in advance what you will do if the director insists on a single number anyway, and prefer publishing the clean partial estimate with its interval over publishing the contaminated one with a caveat.
Follow-up
- The pre-event window has six slices. What standard error does that give you, and is it worth reporting at all?
- How would you choose the burn-in length for the rerun, using data rather than judgement?
- The director ships it anyway on Friday. What do you measure afterwards, and what can that measurement honestly support?
- 01
Describe a situation where you had to influence a decision based on your analysis.
- 02
A two-week live-ops event closed with gross bookings up 18% against the prior week. Your readout says it added no net revenue: summed price_usd_net in fct_iap_transaction over the 28 days spanning the event is flat against a matched window one release cycle earlier, and fct_currency_ledger shows premium-currency sinks falling while faucets from source_system = 'pass_tier' rose. The event owner disputes the readout in a review with their director present. Give the argument you would make in that room, and name the one piece of evidence you would concede.
- 03
A switchback test of a container drop-rate change ran Monday to Sunday on 12-hour slices, randomising the whole region-mode population per slice. On Wednesday a limited-time event went live to everyone, changing both the currency faucet and store traffic for the remaining slices. Treatment and control slices are no longer exchangeable. The change is scheduled to ship Friday and the director wants a number. Give what you say, what you can still salvage from the data, and what you ask for.
Is this an official Pocket Gems interview guide?
No. It is PracHub's own research and practice material for the Data Scientist role at Pocket Gems. Rounds and questions reflect what candidates have reported, not a process Pocket Gems has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗How difficult is the interview process for Data Scientist positions?
The interview process is generally considered average in difficulty, with a mix of technical and behavioral questions. Focused preparation on statistical methods, case studies, and your past experiences will help you stand out.
PracHub interview research ↗What differentiates successful candidates at Pocket Gems?
Successful candidates are those who not only possess strong technical skills but also demonstrate excellent communication and problem-solving abilities. They align well with the company culture and can effectively collaborate across teams.
PracHub interview research ↗What is the typical timeline from initial screen to offer?
The timeline can vary, but candidates often hear back within a few weeks after their initial interviews. The entire process is typically completed within a month.
PracHub interview research ↗Is remote work an option for Data Scientists at Pocket Gems?
While the company has embraced flexible work arrangements, specific policies regarding remote work may vary by team. It's advisable to inquire about this during your interview.
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