Python · SQL · Web Dev · Java · AI/ML tracks launching soon — your one platform for all of IT
Beginner

The Data Science Workflow

From a vague business question to a shipped decision — the six stages every real project moves through, walked end to end on the StreamPulse dataset

12–16 min July 2026

// Part 01

"Analyze the Data" Is Not a Plan

Module 01 introduced the six-stage data science lifecycle in one paragraph each. This module goes through every stage in full depth, because the single biggest reason data science projects stall or produce numbers nobody trusts is skipping one of these stages — almost always without realizing it.

Here is the full sequence again, as a reference you will come back to:

1. Frame
2. Collect
3. Clean & Explore
4. Analyze / Model
5. Validate
6. Communicate & Ship

Notice this is not a strict one-way pipeline. Real projects loop backward constantly — cleaning often reveals that the original question needs reframing, and validation often sends you back to collect more data. Treat the six stages as a checklist you keep returning to, not a straight line you walk once.

// Part 02

Stage 1 — Framing the Question

"Look into user engagement" is not answerable. Nobody — not the world's best data scientist — can write a single query or build a single model against that sentence. Framing is the process of turning a vague request into a precise, testable question, and it is the stage most often skipped under time pressure.

What a precise question actually looks like

Vague requestPrecise, answerable question
"Look into user engagement"What percentage of Premium subscribers watched at least one title in the last 30 days, compared to Basic?
"Figure out why people leave"Which combination of plan and referral_source has the highest cancellation rate in the subscriptions table?
"See if the new feature works"Did average minutes_watched per user increase in the 30 days after the recommendation change shipped, compared to the 30 days before?
"Understand our content"Which genre has the highest average imdb_rating, and does that correlate with how much of each title users actually finish?

Every precise question on the right shares three properties: it names the exact columns involved, it is time-bound (a specific window, not "ever"), and it has a clear answer shape — a percentage, a comparison, a yes/no. If you cannot say what the answer will look like before you start, the question is not framed yet.

🎯 Pro Tip
A useful habit: before opening any code editor, write the exact sentence "If I am right, I expect to see ___." If you cannot fill in that blank, you do not have a question yet — you have a topic.

// Part 03

Stage 2 — Collecting the Data

Once the question is precise, you know exactly which data answers it — and that tells you where to go get it. In this course, collection is done for you: the five StreamPulse tables load automatically into every playground. In a real job, this stage is rarely that simple.

A data warehouse

The most common source. You write SQL against tables a data engineering team maintains — this is exactly why the SQL track pairs so well with this one.

An internal API

Some data only exists behind a service endpoint, not yet in the warehouse. You fetch it programmatically and cache a snapshot for analysis.

Raw log files or event streams

Click and watch events often land first as raw JSON logs before any pipeline structures them — you may need to parse them yourself.

A CSV someone emailed you

Less glamorous, extremely common. Always the least trustworthy source — verify column meanings before assuming anything.

Regardless of the source, one habit matters more than any tool: know exactly where every column came from and what it actually measures before trusting it. The watch_history.minutes_watched column, for example, is only meaningful once you know whether it is logged client-side (can be inflated by buffering) or server-side (more reliable but delayed).

// Part 04

Stage 3 — Cleaning and Exploring

This is the stage covered in full depth in Section 5 (Data Cleaning) and Section 7 (Exploratory Data Analysis) — for now, see it in action. Before trusting any table, run a quick trust check: how many rows, how many missing values, any obvious duplicates.

Loading Python engine…
Ctrl + Enter to run
Loading Python engine… (first run on a page takes a few seconds)

Notice end_date and cancel_reason show missing values — but that is expected here, not a data quality problem: an active subscriber has no end date and no cancellation reason yet. Knowing which missing values are meaningful (active users) versus which are genuine data quality issues (a truly broken record) is a judgment call you make at this stage, before any analysis downstream.

// Part 05

Stage 4 — Analyze or Model

This is the stage people jump to too early. The right method depends entirely on what the framed question actually needs — not on what is more impressive to build.

If the question is…The right method is…
"What happened, grouped by X?"A groupby and a chart. No model needed — Sections 6–8 cover this fully.
"Is this difference real or just noise?"A statistical test (Section 9) — t-test, chi-square, or a proper A/B test.
"What will THIS specific user do next?"A predictive model — regression or classification (Section 10).
"Which factors are associated with an outcome?"Correlation analysis first, a model only if you need to predict, not just explain.
Loading Python engine…
Ctrl + Enter to run
Loading Python engine… (first run on a page takes a few seconds)

That one merge-and-groupby just answered "does cancellation rate differ by plan?" — no machine learning involved, and correctly so, because the question only asked what happened, not what a specific future user will do.

// Part 06

Stage 5 — Validate

A pattern in a groupby result is not automatically real. Validation asks: would this hold up on a different sample, or is it noise dressed up as a finding? Two checks matter most before you trust any result.

Check the sample size behind every percentage

Loading Python engine…
Ctrl + Enter to run
Loading Python engine… (first run on a page takes a few seconds)

A cancellation rate calculated from 3 subscribers is not evidence of anything, even if the percentage looks dramatic. This is the exact reason Section 9 (Statistics) exists — hypothesis testing formalizes exactly how much sample size you need before a difference is trustworthy, instead of eyeballing it.

Ask whether the result would survive a stricter test

If a groupby shows Premium subscribers cancel more than Basic, the immediate next question is: is that a real behavioral difference, or does it just reflect that Premium happened to sign up more recently (less time to prove they stay)? Module 42 (Hypothesis Testing) and Module 44 (A/B Testing) give you the formal tools; for now, the habit to build is asking this question at all, every time.

⚠️ Important
The most expensive data science mistake is not a bug in the code — it is presenting a pattern from a small or biased sample as if it were a validated fact. Always ask "how many rows is this actually based on?" before repeating a number to a stakeholder.

// Part 07

Stage 6 — Communicate and Ship

The deliverable is never the notebook. It is a decision someone else can act on — and the right format depends entirely on the audience.

An executive

One sentence and one number: "Premium cancellation is 18% higher than Basic, based on 25 subscribers — worth a deeper look before we conclude anything."

A product manager

The chart, the caveat about sample size, and one concrete recommendation: run an A/B test before changing Premium pricing.

Another data scientist

The full notebook, the exact filters applied, and the statistical test used to validate the finding.

An ML engineer

A trained, serialized model plus the exact features and preprocessing steps, ready to wire into a production service.

Notice none of these four deliverables is "the notebook, unedited." Translating your own analysis into the right format for the person who has to act on it is a distinct skill from the analysis itself — and it is the stage most technical people underinvest in.

// Part 08

One Question, All Six Stages, Live

Let us run the whole workflow end to end on one real question: "Which referral source brings in subscribers who stay longest?" Watch how each stage shows up as actual code.

Loading Python engine…
Ctrl + Enter to run
Loading Python engine… (first run on a page takes a few seconds)
Loading Python engine…
Ctrl + Enter to run
Loading Python engine… (first run on a page takes a few seconds)

With StreamPulse's small teaching dataset, most referral sources have only 4–6 users each — nowhere near enough to draw a confident conclusion. That is itself the correct, honest output of Stage 5: not a made-up recommendation, but a clear statement that a real answer requires more data before shipping any decision. That instinct — knowing when NOT to conclude something — is what stage 5 is actually for.

// Part 09

What This Looks Like at Work — A Full Day

9:30 AM
A vague Slack message arrives
Your product manager writes: "Can you look into why engagement dropped last month?" You do not open a notebook yet. You reply asking for the exact metric they mean — daily active users, minutes watched, or something else — and the exact date range for "last month."
10:00 AM
The question gets framed
Thirty minutes later you have a precise version: "Did average minutes_watched per active user in June differ from May, and if so, for which subscriber segment?" Now you know exactly which columns and which filter to write.
10:15 — 11:30 AM
Collect, clean, explore
You pull watch_history and users, check for missing dates, confirm the June and May date ranges are complete in the data (no partial month due to a pipeline delay), and look at the overall distribution before slicing by segment.
11:30 AM — 1:00 PM
Analyze, then validate
A groupby shows a real-looking 12% drop, concentrated in the Basic plan. Before reporting it, you check the sample size (large enough) and run a quick statistical test to confirm the drop is unlikely to be random noise.
2:00 PM
Communicate and ship
You send the PM one sentence, one chart, and one caveat: "Basic-plan engagement dropped 12% in June, statistically significant at your usual threshold — likely tied to the price increase that took effect June 1st, worth confirming with an A/B-style before/after comparison next month."

🎯 Pro Tip

Every stage above took roughly the same amount of time. New data scientists often spend 90% of their time on Stage 4 (the model or analysis) and rush stages 1, 5, and 6 — which is exactly backwards from where most real projects actually fail.

// Part 10

Interview Prep — 5 Questions With Complete Answers

Q: A stakeholder asks you to 'look into user engagement.' Walk me through what you do first.

Before writing any code, I would clarify the request into a precise, answerable question. "Engagement" is ambiguous — it could mean daily active users, session length, content completion rate, or repeat visits. I would ask what specific metric they care about, over what time window, and compared against what baseline (last month, a specific cohort, a competitor benchmark).

Once I have a precise version — for example, "did the percentage of Premium subscribers who watched at least one title in the last 7 days change after the pricing update?" — I know exactly which tables and columns I need, what the expected output looks like, and what would count as an interesting versus uninteresting result.

Skipping this step is the most common cause of wasted analysis work — building a thorough report that answers a question nobody actually asked, because the original request was never made precise.

Q: What is the difference between exploratory analysis and validating a finding?

Exploratory analysis is the discovery phase — looking at distributions, running groupbys, and generating hypotheses about patterns that might be present in the data. It is intentionally open-ended and is expected to surface both real signals and coincidental noise.

Validation is the confirmatory phase — taking a specific pattern found during exploration and testing, using statistics, whether it is likely to be real rather than due to chance or a small sample. This typically means checking sample sizes, running a hypothesis test, and considering whether the pattern would replicate on a held-out or future dataset.

The common mistake is treating an exploratory finding as validated fact without doing the second step — reporting the first interesting-looking groupby result as if it were a proven conclusion, when it has not yet been tested for statistical significance or checked against sample size.

Q: Why does defining a success metric before starting analysis matter?

Without a predefined success metric, it is easy to unconsciously search through many possible cuts of the data until one shows an interesting-looking pattern, then present that cut as the finding — a statistical error sometimes called p-hacking or data dredging. If you define the exact metric and comparison you are testing before looking at results, you avoid this bias.

It also makes the eventual result immediately actionable. If the agreed success metric for a feature launch was "7-day retention increases by at least 2 percentage points," the result is a clear yes or no. Without that predefined bar, any result can be spun as a success after the fact, which erodes trust in the analysis over time.

In practice, this means agreeing on the metric and the threshold for success with stakeholders during the framing stage — Stage 1 of the workflow — not after the results are already in hand.

Q: Give an example of when a simple groupby is the right answer, and when you would build a model instead.

A groupby and chart is the right tool when the question is descriptive — "what happened, broken down by category?" For example, "what is the average watch time per device type?" is fully answered by grouping watch_history by device and taking the mean. No model adds value here because nothing is being predicted about an individual, unseen case.

A model is the right tool when the question is genuinely predictive about individual future cases — "will this specific subscriber cancel next month?" cannot be answered by a groupby, because it requires estimating a probability for one new individual based on patterns learned across many past individuals. That requires a trained classification model, covered starting in Module 47.

A common junior mistake is reaching for a model when a groupby would answer the question just as well and be far easier to explain and maintain — model complexity should be justified by the question's actual need for individual-level prediction, not used as a default.

Q: How do you communicate statistical uncertainty to a non-technical stakeholder without either overstating or burying the result?

I lead with the finding in plain language, immediately followed by the confidence level in equally plain language — for example, "Premium subscribers are cancelling about 18% more than Basic subscribers this quarter. This is based on a reasonably large sample and is unlikely to be random noise, but it's correlational — we have not yet tested what happens if we change anything about Premium."

I avoid two failure modes. The first is hiding uncertainty entirely to sound more confident, which leads to decisions made on shakier ground than the stakeholder realizes. The second is burying the actual finding under so much statistical caveat that the stakeholder cannot extract an actionable takeaway at all.

The right balance is usually: the finding, one sentence of confidence context in plain terms (not p-values or confidence interval math), and — when relevant — a concrete next step like running a controlled experiment before committing a large decision to the finding.

// Part 11

Errors You Will Hit — And Exactly Why They Happen

SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame

Cause: You filtered a DataFrame into a new variable, then tried to modify a column on that filtered result. Pandas cannot always tell whether your filtered variable is an independent copy or a view into the original data, so it warns you that the modification may silently not do what you expect.

Fix: Add .copy() immediately after filtering, before modifying: premium = users[users['plan'] == 'Premium'].copy() — then premium['flag'] = True works safely and unambiguously. This is one of the most common warnings in real pandas work and is almost always fixed the same way.

ValueError: You are trying to merge on object and int64 columns for key 'user_id'

Cause: The column you are merging on has a different data type in each DataFrame — for example, user_id is stored as text in one table and as a number in the other, often because one table was loaded from a CSV that quoted the IDs.

Fix: Check the dtype on both sides before merging: users['user_id'].dtype and subscriptions['user_id'].dtype. If they differ, cast one to match the other before merging: subscriptions['user_id'] = subscriptions['user_id'].astype(int) — do this once, right after loading the data, not repeatedly before every merge.

KeyError: 'user id'

Cause: A merge or groupby was written with the column name spelled using a space instead of an underscore — 'user id' instead of 'user_id'. Pandas treats this as looking for a column that does not exist, rather than as a typo it can guess-correct.

Fix: Run df.columns.tolist() to see the exact column names, copy them exactly, and remember that StreamPulse (like almost all real data) uses snake_case with underscores, never spaces, for every column name.

ValueError: cannot convert float NaN to integer

Cause: You tried to convert a column to an integer type using .astype(int), but the column contains missing values (NaN). NaN is fundamentally a floating-point concept — there is no integer representation of 'missing' in NumPy's integer types, so the conversion fails outright.

Fix: Handle the missing values first — either fillna() with a sensible default or dropna() to remove those rows — before converting to int. Alternatively, use the nullable integer type: df['col'].astype('Int64') (capital I) which supports NaN values directly.

TypeError: unhashable type: 'list'

Cause: You tried to use a list as a groupby key or as a dictionary key, for example groupby(['plan', ['country']]) with an extra nested list, or accidentally passed a list where pandas expected a column name string or a flat list of column names.

Fix: Double-check the structure of what you are passing to groupby() — it should be a single column name as a string, e.g. groupby('plan'), or a flat list of column name strings for multiple keys, e.g. groupby(['plan', 'country']) — never a list containing another list.

Try It Yourself

Frame and answer this question end to end: 'Do subscribers who joined through Social Media referrals watch more content on average than subscribers who joined through Organic Search?' Merge users with watch_history, then compare average minutes_watched between the two referral_source groups.

🎯 Key Takeaways

  • The six-stage workflow — frame, collect, clean & explore, analyze/model, validate, communicate & ship — is not a strict pipeline. Real projects loop backward constantly, especially from cleaning back to framing and from validation back to collection.
  • A vague request like "look into engagement" is not answerable. A framed question names exact columns, is time-bound, and has a clear answer shape — a percentage, a comparison, a yes/no.
  • Collection in the real world rarely means "the data is already loaded" — it means knowing exactly which warehouse table, API, or log source has the answer, and what each column actually measures.
  • Missing values are not automatically a data quality problem — an active subscriber having no end_date is expected and meaningful, not an error to "fix."
  • Choosing between a groupby/chart and a trained model should be driven by the question: "what happened, grouped by X" needs a groupby; "what will this specific individual do next" needs a model.
  • Validation means checking sample size and considering whether a pattern would survive a statistical test — the most expensive data science mistake is presenting an unvalidated pattern from a small sample as fact.
  • The deliverable is never the notebook. The right output format — one sentence for an executive, a chart plus caveat for a PM, full code for another data scientist — depends entirely on who has to act on it.
  • Defining a success metric and threshold before looking at results prevents unconsciously searching for whichever data cut looks most interesting after the fact.
  • New data scientists tend to over-invest time in Stage 4 (analysis/modeling) and under-invest in Stages 1, 5, and 6 — exactly backwards from where most real projects actually fail.
  • Knowing when NOT to conclude something — because the sample is too small or the pattern does not survive validation — is as much a professional skill as building the analysis in the first place.

What comes next

Module 03 draws a sharp, practical line between Data Scientist, Data Analyst, ML Engineer, and Data Engineer — what each role actually owns day to day, where the boundaries blur in practice, and how to talk about your own work in interviews without the titles getting confused.

Module 03 → Data Scientist vs Other Roles
Share

Discussion

0

Have a better approach? Found something outdated? Share it — your knowledge helps everyone learning here.

Continue with GitHub
Loading...