I've been asked some version of "how much should I expect to get paid as a data scientist" enough times that I decided to stop guessing and actually build something to answer it, using real data instead of gut feeling or whatever number shows up first on Google. This is a walkthrough of that project — what worked, what didn't, and the mistakes that taught me more than the parts that went smoothly.
The data
I used a public salary dataset covering data science and analytics roles, self-reported between 2019 and 2021 — 258 rows in total, mostly from the US, with fields for job title, years of tenure, location, education, industry, and salary.
It was not clean, and cleaning it took longer than the modeling did:
115 unique job titles for what were really about 8 actual role levels. "Senior Data Scientist," "Senior Data Scientist Lead," "Senior Predictive Analyst," and "Senor Data Analyst" (yes, a typo) were all technically different strings. I grouped them by hand into eight buckets — junior IC, analyst, mid-level data scientist, ML engineer, senior IC, manager/lead, leadership, and other — based on keyword matching against the raw title.
Salaries in inconsistent formats — some as $190k, some as "93,000" with commas and quote marks, some as bare numbers. These needed normalizing before anything downstream would work.
Missing data throughout — tenure was missing for 26 rows, education for 3, and 4 rows had no usable salary at all and had to be dropped, leaving 254 usable rows.
A handful of real outliers, not typos. Three rows — all "Data Scientist" or "Senior Data Scientist" titles on the West Coast — reported salaries between $375,000 and $475,000. I checked these individually rather than deleting them; they're plausible for senior IC/staff-level roles at large tech companies, so I kept them in, which is itself a modeling decision worth being upfront about.
After cleaning: median salary across the dataset was $114,500, with a fairly wide spread (25th percentile $85,000, 75th percentile $150,000).
Approach
Features going into the model: grouped title, years of tenure, US region, education level, and industry group.
I tried two models:
Linear Regression (baseline): R² of 0.27, mean absolute error of about $41,600.
Random Forest Regressor (300 trees, max depth 6): R² of 0.24, MAE of about $43,300 on the same held-out test split. Cross-validation across 5 folds showed the score bouncing between 0.10 and 0.34 depending on the split — a direct consequence of having only 254 rows to learn from.
The Random Forest didn't beat the simple linear baseline. I want to be honest about why, rather than quietly picking whichever number looked better: with a dataset this small, a more flexible model doesn't have enough data to find real non-linear patterns — it mostly just adds variance. The linear model's more constrained assumptions actually generalized slightly better here. That's a useful lesson on its own: more complex isn't automatically better, especially under 300 rows.
What actually mattered
Looking at feature importance from the Random Forest (grouped by category, since one-hot encoding splits each into several columns):
Job title / seniority group mattered most overall (about 30% of total importance) — unsurprising, but useful confirmation.
Region was close behind (about 24%) — West Coast roles had a median salary of $145,000 versus $86,000 for Southeast roles and $86,000 for non-US roles in this sample, the widest gap in the whole dataset.
Years of tenure alone (as a single numeric feature, not grouped) was actually the single most important individual feature — more predictive than any one title or region category.
Education showed a real gap too — PhD holders had a median of $155,000, versus $110,000 for Master's and $95,500 for Bachelor's — though I'd treat this cautiously since PhD and leadership-title rows likely overlap.
By seniority group, medians ranged from $185,000 (leadership) down to $49,000 (junior IC), with a genuinely odd result in between: the "ML engineer" group's median came out lower ($80,000) than mid-level data scientists ($110,000), which contradicts what I expected going in. With only 9 ML-engineer rows in the whole dataset, this is almost certainly a small-sample artifact rather than a real market signal, and I'm flagging it rather than smoothing it over.
Where this falls short
254 rows is small for 5 categorical features with many levels between them — several title/region/education combinations have only a handful of examples, so predictions for those specific combinations are shakier than the headline R² suggests.
The data is from 2019–2021. Tech and data science compensation has moved a lot since then; treat this as a lesson in method, not as current market pricing.
Self-reported data carries the usual bias risks — people who respond to salary surveys aren't a random sample of the whole field.
An R² of ~0.27 means the model explains roughly a quarter of the variance in salary — useful for spotting directional patterns (seniority, region, education all matter, in that rough order), not precise enough to quote a confident number to a specific person.
What I'd do differently
Next time I'd spend less effort tuning the Random Forest and more effort either finding a larger dataset or engineering better features from what little text data exists (like extracting seniority signals more carefully from free-text titles instead of keyword-matching by hand). Given how much of the "title" signal was really just noisy text, a cleaner NLP-based title-normalization step would likely have helped more than switching models did.
Code
Full cleaning and modeling code: github.com/DostonUr/DataScience_Salary
If you've worked with a similar dataset or see a flaw in how I handled the outliers or the title grouping, I'd genuinely like to hear about it — reply here or find me on LinkedIn.
Top comments (0)