At the University of North Texas (UNT), the Data Scientist role—frequently operating under the title of Research Scientist—is a deeply impactful position that bridges rigorous analytical methodologies with hands-on scientific discovery. Whether you are analyzing complex behavioral data to scale Applied Behavior Analysis (ABA) programs at the Kristin Farmer Autism Center or processing advanced transcriptomic data in the Vascular Biology Laboratory, your work directly influences both academic innovation and community well-being.
This role is critical because it transforms raw experimental and clinical data into actionable insights, novel intervention approaches, and publishable scientific literature. You are not just crunching numbers; you are an essential driver of research programs that address complex social, biological, and health-related issues. Your analytical rigor ensures that UNT continues to produce high-quality, evidence-based solutions that transform lives and create economic opportunities.
Expect a dynamic, interdisciplinary environment where you will leverage state-of-the-art approaches—from single-cell RNA sequencing analysis to systematizing service delivery frameworks. You will work closely with clinical directors, principal investigators, and faculty, acting as the analytical backbone of your respective laboratory or center. This position requires a unique blend of domain-specific knowledge, advanced data handling capabilities, and a deep commitment to UNT’s people-first, values-based culture.
Initial Screening Call
reportedWhoever 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
Deep-Dive Technical Interview
reportedA handful of shapes account for most of what gets asked in this format: a ranking or deduplication inside groups, a running or rolling total, a period-over-period comparison, and a cohort tracked forward over time. Recognising the shape quickly is most of the speed here; deriving it from scratch while a clock runs is where the time goes. Know that a window function keeps every row while a GROUP BY collapses them, and know which one the question needs. If the exercise is in Python instead of SQL, the same shapes arrive as groupby with transform, shift and merge, and the same grain mistakes are available.
What to demonstrate
- Whether you reach the right construct without a detour, such as ROW_NUMBER over a partition to deduplicate instead of a self-join against a MAX subquery
- Whether you know what your window frame actually is, since adding ORDER BY inside OVER changes the default frame and silently changes a running total
- Whether the thing runs. A near-miss that throws an error scores below a plainer query that returns the right rows.
How to prepare
- Write each of the four shapes once from memory against a small schema and keep the working version somewhere you will reread it: dedupe with ROW_NUMBER, a running total, a month-over-month change with LAG, and a retention table
- Compute one running total twice on data with tied timestamps, once on the default frame and once with ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, and look at where the two disagree
- If Python is on the table, rebuild the dedupe and the running total with groupby and cumsum, then assert the two implementations return identical rows
Comprehensive Panel Interview
reportedWhere a loop ends with a senior leader, that conversation is rarely another skills test. The technical signal already exists by then, so the questions tend to open up: what you would look at first, where a metric you have heard about could mislead, what you would push back on. The decision being made is scope, which in practice means level and how much you would be trusted to own unsupervised. Treating it as a formality is the usual mistake. An open question late in the day is still being scored, and a vague answer reads as someone who has not run anything themselves.
What to demonstrate
- Whether your view of the business has anything specific behind it, given that you are working only from what is public and are expected to say so
- Whether the scope of work you describe owning matches the scope of the role, instead of sitting a level below it
- Whether you can disagree with something concrete and stay useful about it, rather than agreeing with everything said in the room
- Whether your questions are ones only this person could answer, as opposed to ones the recruiter already covered
How to prepare
- Build one view you could defend for two minutes using only public information: what the funnel probably looks like, which metric likely drives decisions, and where that metric could mislead. Being wrong for a stated reason survives this round; having no view does not
- Write down the largest piece of work you have owned from question to decision, who else touched it, and what you decided alone, then check that it reads at the level you are interviewing for
- Prepare one thing you would want changed if you joined and phrase it as a question rather than a verdict, so it opens a conversation instead of closing one
PracHub editorial advice for the preparation topics above.
Consent and age rules silently truncate the data, not just the joins.
Where age_gated is TRUE, behavioural logging and cross-system joins are restricted, so those learners are missing from the very tables used to compute engagement. An analysis that simply inner-joins will produce a population skewed to older learners and self-serve accounts while appearing complete. Check the age_gated share of every population you report on, and state it.
Learner-level standard errors on class-level interventions.
Anything an instructor controls, and anything deployed by school, is assigned at the section or school level, and outcomes within a section are correlated through the shared instructor, schedule, and device fleet. Treating the learner as the unit of independence understates variance by the design effect 1 + (m - 1) * rho for roughly equal cluster sizes. At a typical section size of 25 and rho of 0.15 that is a factor near 4.6 on variance, which routinely converts a null into a 'significant' result.
Ending an analysis without a recommendation or next step
Close with what you would do and what would change your mind, stated as a condition you can check later. If the evidence is genuinely inconclusive, recommend the specific next measurement and say what it costs in time or exposure.
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.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Attach the calibration in force without merge_asof
You have responses (response_id, content_item_id, submitted_at, is_correct) and calibration_history (content_item_id, valid_from, valid_to, irt_a, irt_b), where intervals within an item are non-overlapping and the open interval carries valid_to as NaT. Attach to each response the irt_a and irt_b in force at submitted_at. You may not use pandas.merge_asof and you may not apply row-wise. responses has about 5 million rows, calibration_history about 40 thousand. Return the input frame plus two columns, NaN where no interval covers the timestamp.
Approach
- Sort calibration_history by (content_item_id, valid_from) and factorise content_item_id across both frames into a shared integer code, so an unknown item on the response side is detectable immediately rather than joining to nothing.
- Convert both timestamps to int64 seconds and build one composite key per side, code * 2**32 + seconds. With codes well under two billion and seconds near 1.8e9, that stays inside int64 and makes a single global search possible. State the second-level resolution assumption; interval boundaries are set at second granularity, so nothing is lost.
- Call np.searchsorted(calibration_keys, response_keys, side='right') - 1 once over the whole array. That gives, for each response, the position of the latest interval starting at or before it within the same item, because the composite key orders by item first.
- Invalidate bad candidates in two places: index -1, and a candidate whose code does not match the response's code, which happens when a response precedes its item's first interval and lands on the previous item's last row.
- Invalidate a third case that is easy to miss: the candidate has a non-null valid_to and submitted_at is at or after it, meaning the response falls in a coverage gap. Without this the previous interval's parameters leak onto uncovered responses.
- Take the parameters positionally with np.take and write NaN where any invalidation fired.
Follow-up
- A backfill wrote overlapping intervals for 200 items. How do you detect that before the join rather than after, and what do you do with those responses?
- The join is correct but peak memory is unacceptable. What changes, and which part of the approach survives?
- How would you test this without a golden output to compare against?
Simulate the gain a bottom-quartile selection manufactures
Observed quiz scores are a true score plus independent noise, both normal, with reliability r equal to true-score variance over observed-score variance. Simulate 200,000 learners, standardise the pretest to mean 0 and SD 1, select the bottom quartile on the pretest, and measure the mean pretest-to-posttest change with no intervention at all. Report the manufactured gain for r in {0.5, 0.7, 0.9, 1.0}, and give the closed form your simulation should reproduce. Use numpy only, no statistical packages.
Approach
- Parameterise by r directly: draw the true score with variance r and each noise term with variance 1 - r, so the observed score has unit variance and reliability exactly r by construction. Draw one true score and two independent noise terms per learner.
- Select on the pretest and only the pretest. Selecting on the true score, or on the average of the two measurements, removes the correlation between selection and the pretest's own noise, and the artefact disappears. That sensitivity is the lesson.
- Compute the mean of posttest minus pretest over the selected group. The true score cancels in the difference, so whatever remains is entirely the difference of two noise draws conditioned on the first being low.
- Check against the closed form. For jointly normal standardised scores, E[posttest | pretest] = r * pretest, so the expected gain is (1 - r) * |E[pretest | bottom quartile]|, and E[pretest | bottom quartile] = -phi(z_0.25) / 0.25 = -1.2711.
- Extend the script with a control group selected by the identical rule from an untreated population and show the difference of differences returns to zero. That is the design fix you would actually propose, not a caveat in a footnote.
Worked solution 25 min
- For each r: t = rng.normal(0, sqrt(r), n); e1, e2 = rng.normal(0, sqrt(1 - r), n) twice; pre = t + e1; post = t + e2.
- sel = pre <= np.quantile(pre, 0.25); gain = (post[sel] - pre[sel]).mean().
- Compare gain to (1 - r) * 1.2711 and print the absolute difference.
- Repeat the whole loop over the four r values and tabulate simulated against closed form.
- Add the untreated control arm selected by the same rule and report the difference of differences.
Follow-up
- A published case study reports large gains specifically for learners who started in the bottom quartile. What do you ask for before believing any of it?
- The posttest is twice as long as the pretest, so its reliability is higher. Does the manufactured gain grow or shrink, and why?
- Give a design that measures a real effect on exactly this selected population without a randomised control.
Audit response rows against the versioned content dimension
Write a check function over fct_assessment_response (response_id, learner_id, content_item_id, content_version_no, attempt_no, submitted_at, scoring_mode, scored_at, score_points, max_points) and dim_content_item (content_item_id, version_no, status, published_at, retired_at). Return one row per check with check_name, failing_count, denominator, and up to five example response_ids. Cover at least four checks: version pairs missing from the dimension, responses submitted before published_at or after retired_at, attempt_no that is duplicated or not gapless from 1 within a learner and item, and rubric_human rows still unscored more than 5 days after submitted_at.
Approach
- Do the existence check as a left merge on the pair (content_item_id, content_version_no) to (content_item_id, version_no) with indicator=True. Joining on content_item_id alone both hides the defect you are looking for and fans rows out by the number of versions per item.
- Evaluate the publication window only on rows that matched, and treat NULL retired_at as open-ended. Report the two directions separately: an early submission points at a publishing race, a late one points at a retirement that never removed the item from a live form.
- For attempt_no, group by (learner_id, content_item_id) and compare the sorted attempts to range(1, n+1). A duplicate and a gap are different defects with different causes, so emit them as two rows.
- For scoring lag, restrict to scoring_mode = 'rubric_human' with scored_at null and submitted_at older than 5 days. Anything more recent is expected lag, not a defect, and counting it makes the check permanently red.
- Give every check its own denominator. A shared total row count makes the version check look negligible and the attempt check look enormous when neither is true, because their natural units are rows and (learner, item) groups respectively.
Follow-up
- Which of these four would you page someone about at 2am, and which is a ticket for the week?
- How do you keep this check from timing out once the fact table is in the billions of rows, without weakening what it detects?
Seat activation rate by institution within thirty days
You have dim_learner(learner_id, org_id, created_at, first_activity_at, current_status) and fct_subscription_period(subscription_period_id, account_id, org_id, seats_purchased, seats_provisioned, period_start, period_end, status), plus dim_term(term_id, org_id, term_start_date). For each org and term, return the share of provisioned seats whose learner's first activity falls inside the 30 days beginning at term_start_date, meaning first_activity_at >= term_start_date AND first_activity_at < term_start_date + 30 days. The denominator is seats_provisioned on the subscription period covering term_start_date, not a count of learner rows. first_activity_at is NULL for a seat that was created but never used, and dim_learner stores one first-ever activity per learner, so this measures new-seat activation inside a rollout window and not per-term usage. Report orgs where seats_provisioned exceeds seats_purchased rather than clipping them.
Approach
- Pick the covering subscription period with term_start_date BETWEEN period_start AND period_end. If overlapping renewal rows both match, choose a deterministic tie-break such as the latest period_start and say so, because the denominator is otherwise ambiguous.
- Write the window closed at both ends: COUNT(DISTINCT learner_id) where dim_learner.org_id matches and first_activity_at >= term_start_date AND first_activity_at < term_start_date + INTERVAL '30 days'. The lower bound is the load-bearing half. With only the upper bound, every learner who activated in any earlier term still satisfies the predicate, so each term inherits all of its predecessors' activations, the rate climbs past 1 on orgs that renew, and the movement has nothing to do with the rollout being measured.
- The NULL is the signal for a dead seat. A NULL first_activity_at fails both bounds on its own, so no explicit IS NOT NULL is needed, but the predicate must live in the numerator aggregate and never in a WHERE clause that also feeds the denominator: an unused seat still occupies a provisioned seat.
- Take the denominator from seats_provisioned on the period. Counting dim_learner rows instead removes never-activated seats from both sides of the fraction and pushes the rate toward 1.
- Mind the types. term_start_date is a DATE and first_activity_at is a timestamp, so the window opens at midnight of term_start_date in whatever zone the timestamps carry and closes at midnight 30 days later. State the zone you are assuming rather than letting the cast pick one.
- LEFT JOIN the learner aggregate onto the period so an org with zero activations returns 0 rather than disappearing from the result set, and emit an over_provisioned flag where seats_provisioned > seats_purchased instead of capping the denominator. Over-provisioning is a contract fact and hiding it makes activation look worse than the contract says.
Follow-up
- dim_learner stores one first-ever activity, so an org with a stable roster shows activation falling every term as returning learners are already spent. What would you add to the model to measure per-term activation, and which of the two does an administrator actually want?
- seats_provisioned can also trail the number of accounts on the license. What does your rate do then, and what do you report instead of a number above 1?
- An administrator wants this weekly during the first month of term. What does the metric look like on day 3, and how do you present a partially matured cohort?
Daily scored submissions under rubric scoring lag
fct_assessment_response(response_id, learner_id, content_item_id, content_version_no, submitted_at, is_correct, score_points, max_points, scoring_mode, scored_at) stores both timestamps in UTC. scored_at is NULL until a rubric item is graded and lags submitted_at by days when scoring_mode = 'rubric_human'. Produce two dense daily series over the last 90 days: submissions keyed on submission date, and completed scorings keyed on scored date. Then state the reporting lag after which each series stops moving, computed from the data rather than asserted, and say what biases your lag estimate.
Approach
- Key the two series on different columns on purpose: date(submitted_at) for volume, date(scored_at) for graded throughput, with scored_at IS NOT NULL on the second. They answer different questions and are not two versions of one number.
- Define scored as scored_at IS NOT NULL rather than is_correct IS NOT NULL. Check first whether rubric rows carry score_points with is_correct left NULL after grading; if they do, the is_correct test undercounts by exactly the rubric share.
- Estimate lag empirically with percentiles of scored_at - submitted_at grouped by scoring_mode. This is computed only over rows already scored, so it is survivorship-biased downward. Report alongside it the share of submissions in each age bucket still unscored.
- Generate a dense date spine and LEFT JOIN both series onto it so a zero-volume day is a 0, not an absent row that a chart will interpolate across.
- Name the timezone problem instead of guessing: these tables carry a locale on the learner but no timezone, so a local-calendar day series is not computable from this schema. Say that rather than pretending date(submitted_at) is an institution's day.
Worked solution 15 min
- Build the date spine for the 90-day window, then the two aggregates, then join.
- Run a distribution of is_correct for rows with scored_at IS NOT NULL to decide which column defines scored.
- Compute median and p95 of scored_at - submitted_at per scoring_mode, and the unscored share by 1, 3, 7 and 14 day age buckets.
- Write one sentence stating the reporting lag you are imposing and what it costs.
Follow-up
- The last five days of the submitted series will be revised upward as late rows land. How do you present a series whose recent points are known to be incomplete?
- Rubric grading is done by people with weekly schedules. What does that do to a daily scored series, and would an ISO week grain be more honest?
- If you had to pick a single cut-off date after which the data is considered final, how would you derive it and what percentage of eventual scorings would you be discarding?
How do you prioritize your time when managing multiple research projec…
How do you prioritize your time when managing multiple research projects with competing deadlines?
Approach
- Fix the population and the time window before naming any metric.
- State what result would change your recommendation, so the answer is falsifiable.
- Name one primary metric, then the guardrail that stops it being gamed.
Follow-up
- Which segment would you cut first, and what would that rule out?
- What would you do if the primary metric and the guardrail moved in opposite directions?
How do you approach designing an experiment or intervention from scrat…
How do you approach designing an experiment or intervention from scratch based on a high-level hypothesis?
Approach
- Say whether units interfere with each other, and switch design if they do.
- State the primary metric and the minimum effect worth shipping, then size the test.
- Name the randomisation unit first; it decides the variance and what the test can detect.
Follow-up
- How would you handle interference between treated and control units?
- What would you conclude if the result is positive but the test is underpowered?
What is your process for maintaining detailed and compliant experiment…
What is your process for maintaining detailed and compliant experimental records?
Approach
- Name the guardrails that would stop a launch even on a positive primary result.
- Decide the analysis before seeing data, including how long it runs and when you look.
- 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?
Describe a situation where an experiment or clinical intervention fail…
Describe a situation where an experiment or clinical intervention failed. What steps did you take to troubleshoot the issue?
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.
- Name the randomisation unit first; it decides the variance and what the test can detect.
Follow-up
- How would you handle interference between treated and control units?
- What would you conclude if the result is positive but the test is underpowered?
Give an example of a complex operational problem you solved within a l…
Give an example of a complex operational problem you solved within a lab or clinical setting.
Approach
- Say what you would check first and why it is the highest-information step.
- State your assumptions explicitly before working the problem.
- Clarify what is being asked and what a complete answer would contain.
Follow-up
- How would you know your answer was wrong?
- What assumption would you test first?
How do you ensure accuracy and reproducibility when conducting high-vo…
How do you ensure accuracy and reproducibility when conducting high-volume data collection?
Approach
- State your assumptions explicitly before working the problem.
- 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?
Design a renewal-risk view with actionable lead time
Three institutional accounts. A: seat activation 0.92, pace adherence 0.71, 120 days to renewal, $8,000 MRR. B: 0.41, 0.55, 45 days, $2,500. C: 0.58, 0.30, 210 days, $6,000. Sources are fct_subscription_period (period_end, mrr_usd, seats_provisioned), dim_learner.first_activity_at and fct_enrollment (units_completed, units_total). Rank them for intervention, state the single metric you would put on an institutional health score, and say precisely what that metric fails to capture.
Approach
- Convert the signals into a decision rather than a score. What matters is recoverable revenue: dollars at risk, times the probability the signal predicts non-renewal, times the probability an intervention can land before period_end.
- Rank on that product. C is the target: the largest addressable gap, $6,000 MRR and 210 days in which a pacing or assignment intervention can still change the term. B is in the worst absolute state but has 45 days left, so this term is effectively spent and it routes to a commercial conversation rather than a product fix. A is healthy and gets monitoring.
- Pick seat activation measured at a fixed term-week as the single health-score metric. It is the earliest available signal, it exists before any outcome does, and it points at causes an administrator can act on: rostering, licence assignment, device access, SSO configuration.
- State the blind spots plainly: activation says nothing about depth, so a seat that opens one item a month counts as activated; it does not say whether the activated learners are the cohort the licence was bought for; and it is silent on instructor adoption, which drives everything downstream and appears nowhere in these three numbers.
- Weight the roll-up by MRR or seats, because net revenue retention is measured in dollars and a hundred small healthy accounts do not offset one large account at 0.41.
- Validate the score against the prior renewal cycle before anyone acts on it, so the thresholds come from observed outcomes rather than from intuition.
Worked solution 25 min
- Write the ranking rule as dollars at risk times predicted risk times a time-to-act factor that decays as period_end approaches.
- Apply it: C first (largest gap, 210 days, $6,000), B second with the routing note that it is a renewal conversation not a product intervention, A third as monitoring only.
- Define the health-score metric: MRR-weighted seat activation at term-week 4, with the SQL sources named per column.
- List the three things activation does not capture, and state how each would be observed separately.
Follow-up
- How does your ranking change for an org in its first term versus its third renewal?
- How do you stop the score firing on an org whose term starts later than your measurement window assumes?
- Which of these three numbers would you show the administrator, and which stays internal?
Activation flatlines across four hundred accounts in one term
Seat activation for the current term reads 0.12 across 400 institutional accounts against 0.58 last term, and dim_learner.first_activity_at is NULL for most learners created this term. Tables: dim_learner (learner_id, org_id, created_at, first_activity_at, age_gated) and fct_lesson_activity partitioned on activity_date (activity_id, learner_id, started_at, device_type, session_id). Before anyone contacts a single account, establish whether learners stopped showing up or rows stopped arriving. Deliverable: the ordered checks and the specific evidence each one produces.
Approach
- Separate absence of behaviour from absence of data as the first move: count rows and distinct learner_id in fct_lesson_activity per activity_date for sixty days, and compare against the same term-week a year earlier and against the trailing median. A collapse in loaded rows is a load question; normal row volume with fewer distinct learners is a behaviour question.
- For each suspect partition compute MIN and MAX started_at within it. A partition whose max started_at truncates mid-afternoon UTC while its neighbours run to end of day is an interrupted load, and that signature is not something learner behaviour produces.
- Establish how first_activity_at is maintained. If the deriving job is incremental and reads only the current partition, learners whose first row landed in a failed partition keep first_activity_at NULL permanently; re-running today fixes nothing and only a backfill plus recompute will.
- Cut the deficit by org_id and device_type to localise the fault. A client SDK or single ingestion shard failure hits a subset of orgs or one device_type; a warehouse job failure hits every org on identical dates with the same shape.
- Check the age_gated share of the affected population before concluding, since consent rules restrict behavioural logging for those learners and their absence from fct_lesson_activity is by design rather than a defect.
Follow-up
- What monitor would have caught this before the activation metric did, and what threshold would you set on it?
- The partitions are backfilled, but a downstream renewal-risk model already scored these orgs on the broken data. What do you do about the scores it produced?
For a candidate whose interviews will centre on A/B testing, metric movement and causal claims. Design comes before arithmetic, arithmetic before analysis, and the week ends by rehearsing the readout rather than the derivation.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Design one test end to end on paper
- Take a single feature change and write the full design: randomization unit, the exact point of exposure, the primary metric with its grain, guardrails, allocation, planned duration, and the decision rule committed before any data exists.
- Write why the randomization unit must sit at or above the level where treatment can spill over, and give one case where user-level randomization is still contaminated (shared accounts or devices, or two participants in the same marketplace).
- State in advance what you will do if the primary metric is flat while a secondary metric is significant.
Deliverable: A one-page test design with a decision rule written before launch.
Practice prompt ↗Practice prompt ↗Practice prompt ↗Worked solution ↗02Power arithmetic until it is automatic
- Compute required sample size per arm for a binary metric with the normal approximation, n is approximately 2 times (z for alpha/2 plus z for power) squared times p(1 minus p) divided by delta squared, for baselines of 2, 10 and 40 percent at a 5 percent relative lift, and note that for a fixed relative lift the requirement falls as the baseline rises because delta grows proportionally with p.
- Redo the calculation for a continuous metric using variance in place of p(1 minus p), and show why a heavy-tailed quantity such as revenue per user needs either far more traffic or a capped version with a stated cap.
- Convert one of the results into weeks given a weekly eligible traffic figure, then list the two honest ways to shorten it (accept a larger detectable effect, or reduce variance) and write why quietly lowering the power target is a decision to miss more real wins, not a speedup.
Deliverable: A small script or sheet that maps baseline, minimum detectable effect, alpha and power to sample size and weeks, cross-checked against a published calculator.
Practice prompt ↗Practice prompt ↗Practice prompt ↗03Variance and the unit-of-analysis problem
- Take a ratio metric whose denominator is not the randomization unit (clicks per session, randomized by user) and compute the standard error twice, once naively at session level and once by the delta method or a user-level bootstrap, then record how much the naive version understates it.
- Implement CUPED on simulated data: choose a pre-period covariate X measured before assignment, estimate theta as Cov(Y, X) divided by Var(X), and analyse Y minus theta times (X minus its mean) in place of Y. Confirm the variance of the adjusted outcome equals the raw variance multiplied by one minus the squared correlation between Y and X, so a correlation of 0.45 removes about 20 percent of the variance and not 80.
- Now run that simulation a few hundred times and confirm the adjusted effect estimate is unbiased for the same effect rather than numerically identical to the raw one. Within any single run the two differ, sometimes by a large fraction of the true effect, because the two arms' pre-period covariate means never coincide exactly in a finite sample; they agree in expectation, which is the property that matters and the one to state out loud.
Deliverable: A notebook showing the adjusted estimator with a measurably smaller variance than the raw one, plus a repeated-simulation table showing the two estimators agreeing on average while differing run by run.
Practice prompt ↗Practice prompt ↗04Validity threats you can actually test for
- Run a sample ratio mismatch check as a chi-square goodness-of-fit test against the intended allocation, and write the three causes you would chase first (assignment logged before exposure, an arm-specific redirect or load failure, bot filtering applied asymmetrically).
- Simulate peeking: generate A/A data, test daily at alpha 0.05 across 14 looks, record the inflated false positive rate, then apply an alpha-spending boundary or commit to a fixed horizon and confirm the rate returns to nominal.
- Write how you would separate a novelty effect from a durable lift using the treatment effect plotted against days since first exposure, and what shape would change your recommendation.
Deliverable: One table showing the peeking false positive rate before and after correction, plus a written SRM triage list.
Practice prompt ↗Practice prompt ↗Worked solution ↗05When randomization is not available
- Write the identifying assumption for difference-in-differences (parallel trends in the absence of treatment), then plot pre-period trends for two candidate control groups and justify rejecting one of them.
- Design a switchback test for a change where user-level randomization would leak across participants, choosing a time-block length against the carryover you expect and saying how you would detect carryover in the data.
- List what an interrupted time series or a synthetic control buys you and the one thing neither can rule out: an unobserved shock that coincides with the launch.
Deliverable: A one-page memo recommending a single quasi-experimental design and naming its weakest assumption explicitly.
Practice prompt ↗Practice prompt ↗06The readout query
- Write the assignment-to-exposure join that returns exactly one row per unit per experiment, and handle units appearing in both arms by excluding and counting them rather than silently keeping one.
- Compute the per-arm metric, its variance and the relative lift with a confidence interval in SQL, then reproduce the identical numbers in a notebook as a cross-check.
- Add a segment breakdown and write the sentence that keeps it from being p-hacking: segments declared in advance, everything else reported as exploratory and corrected for multiplicity.
Deliverable: A single query that outputs the full readout table, matched to a notebook recomputation.
Practice prompt ↗Practice prompt ↗07Present it to someone who will not read the appendix
- Give a 10-minute readout of a real or simulated experiment in the order decision, number, uncertainty, caveat.
- Have your listener ask "can we ship it" in the case where the primary is flat and a guardrail moved, and answer with a recommendation rather than a request for more data.
- Rewrite your opening line so the recommendation lands before any methodology.
Deliverable: A one-page readout whose first line is the recommendation.
Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
Nearly every data role forces a trade between the analysis you want and the one that fits the decision window. Prepare a case where you deliberately shipped something less rigorous, named the weakness to the person relying on it, and said what would change your answer. The naming is the part interviewers listen for.
Describe a time when you had to adopt a new analytical tool or laborat…
Describe a time when you had to adopt a new analytical tool or laboratory technique. How did you get up to speed?
Approach
- State the situation in two sentences and spend the rest on your reasoning.
- 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 your approach to training and mentoring undergraduate student…
Describe your approach to training and mentoring undergraduate students who may have no prior research experience.
Approach
- Quantify the outcome, including what you would not claim credit for.
- 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.
Follow-up
- How did you know the outcome was caused by your change?
- What did you decide not to do, and why?
Allocate one week across three competing team requests
In one week you receive three requests. Sales wants a renewal-risk list for 40 institutional accounts whose period_end falls in 30 days. Curriculum suspects an item-quality problem on a published unit that is currently collecting responses. Growth wants a signup-flow test sized. You have capacity for roughly one and a half of them and cannot escalate for arbitration. Deliverable: your allocation, the reasoning you give each requester, and the one question you ask each before deciding. Probed: whether you prioritise on decisions and reversibility rather than on who asked loudest.
Approach
- Score each request on deadline and reversibility, not on seniority. The renewal list is worthless after period_end; a bad published item compounds with every response collected against it; a test sizing costs almost nothing to delay a week.
- Ask each requester the one question that could collapse their request: whether sales already has a workable heuristic list, whether the suspect unit can simply be set to retired today, whether the growth test has a launch date at all.
- Look for the cheap partial that still buys the deadline. A rules-based risk cut from first_activity_at, units_completed against units_total, and days to period_end ships in a day and captures most of the value of a model.
- Decide, then tell the person who is not getting the work directly and with a date. Unmanaged silence costs more trust than an explicit decline.
- Write the decision and its reasoning somewhere durable so next week's triage does not relitigate the same three requests.
Follow-up
- The growth PM escalates to your skip-level. What do you do, and what do you send ahead of that conversation?
- Two weeks later the risk list you shipped went unused. What changes in how you triage next time?
- 01
Describe a time when you had to adopt a new analytical tool or laboratory technique. How did you get up to speed?
- 02
Describe your approach to training and mentoring undergraduate students who may have no prior research experience.
- 03
In one week you receive three requests. Sales wants a renewal-risk list for 40 institutional accounts whose period_end falls in 30 days. Curriculum suspects an item-quality problem on a published unit that is currently collecting responses. Growth wants a signup-flow test sized. You have capacity for roughly one and a half of them and cannot escalate for arbitration. Deliverable: your allocation, the reasoning you give each requester, and the one question you ask each before deciding. Probed: whether you prioritise on decisions and reversibility rather than on who asked loudest.
Is this an official University of North Texas interview guide?
No. It is PracHub's own research and practice material for the Data Scientist role at University of North Texas. Rounds and questions reflect what candidates have reported, not a process University of North Texas has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗How long does the interview process typically take?
Academic and university hiring processes can be highly rigorous and sometimes move slower than the corporate tech sector. Expect the process to take anywhere from 4 to 8 weeks from the initial screen to the final offer, depending on the committee's schedule and the academic calendar.
PracHub interview research ↗What differentiates the most successful candidates for this role?
Successful candidates seamlessly bridge the gap between deep technical execution and high-level scientific storytelling. They don't just know how to run an assay or write a script; they know how to interpret that data, explain its significance to a multidisciplinary team, and use it to mentor junior researchers.
PracHub interview research ↗Is this role fully remote, hybrid, or onsite?
Given the hands-on nature of the work—whether it involves managing genetically engineered mouse models in a lab or overseeing clinical interventions at the Autism Center—these positions are typically onsite in Denton, TX.
PracHub interview research ↗How much emphasis is placed on UNT's specific values during the interview?
A significant amount. UNT is very proud of its people-first culture. Interviewers will actively look for evidence that you practice "Courageous Integrity" (e.g., being honest about data limitations) and "Better Together" (e.g., a strong track record of collaborative research).
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