๐Ÿ“Š Data Job Market Intelligence

An end-to-end pipeline that collects data-job postings from 6 public APIs, extracts the skills and salaries hidden in their text, and compares markets โ€” including a focus on Indonesia vs. remote-international roles.

Key findings

From 2,367 postings across 5 markets and 6 sources, accumulated by a weekly scheduled collector. Directional, not definitive โ€” they sharpen as the data grows.

Python + SQL
lead demand in every market (19% and 14% of all postings) โ€” the non-negotiable core for data roles.
$112k โ†’ $162k
median advertised salary rises Analyst โ†’ Scientist โ†’ ML Engineer, normalized to USD/year.
5 markets
Remote-international, US, Australia, Malaysia & Indonesia โ€” each tagged and comparable.

๐ŸŒ Indonesia vs. remote-international

The markets want different things โ€” useful if you're deciding which to target.

Indonesia (local, n=33)Remote-international (n=1,362)
SQL 61%, Python 58%Python 28%, SQL 19%
Tableau 30%, Power BI 27% BI-heavyAWS 18%, Git 13% cloud/eng
Statistics 33%, ETL 27% analyst coreMachine Learning 14%, Kubernetes 11%

Indonesian roles lean analyst / BI (SQL + a BI tool are near-mandatory); remote roles lean Python + ML + cloud.

Charts

Generated reproducibly from the warehouse (python -m src.figures).

Most in-demand skills
Most in-demand skills across all postings.
Median salary by skill
Median advertised salary by skill (advertised only, normalized to USD/year).
Postings and pay by role
Volume and median pay by role family.
Skill co-occurrence
Which skills appear together (Python+SQL is the backbone).

๐Ÿค– Predicting advertised salary

693 postings carry a genuinely advertised salary, from 293 companies. The interesting part is where the accuracy came from.

ModelMAERยฒ (grouped)
Baseline: predict the median$50.4k-0.02
Role + skills only$46.5k0.12
+ location / source / market$37.4k0.37
+ description features$37.0k0.38
Gradient boosting$39.9k0.27
Blend of two ridge models$33.5k0.46

Rยฒ went from 0.12 to 0.46 without changing the algorithm. Every point came from data work: normalizing currencies and pay periods (+26% usable rows), using the location, source and category columns that were already collected but never read, and mining the ~6,600-character job descriptions for required years of experience. Gradient boosting lost to the linear model.

Predicted vs actual salary on held-out companies
Out-of-fold predictions on companies the model never saw in training.

A leak I found in my own evaluation. 293 companies supply those 693 postings, so a random train/test split routinely puts the same employer on both sides and the model simply memorises that company's pay band. Switching to GroupKFold by company lowered the headline Rยฒ from 0.56 to 0.46. The lower number is the real one, and both are reported side by side.

How it works

Collect โ†’ normalize โ†’ extract skills โ†’ analyze โ†’ model โ†’ dashboard. Tested (55 unit tests, CI on every push, including a smoke test that runs the whole dashboard) and reproducible.

Sourcing
6 public APIs (Remotive, Jobicy, RemoteOK, Adzuna, Jooble, JSearch) into one normalized, deduplicated warehouse, refreshed weekly by GitHub Actions.
Skill extraction
Curated taxonomy + a matcher that resolves ambiguous names (R vs "R&D", Java vs JavaScript, Excel vs the verb).
Modeling
Baselines first, cross-validation grouped by company, and interpretable coefficients โ€” designed so the honest number is the one on display.

Honest by design: Adzuna-predicted salaries are excluded from pay stats; demand is audited per source (some APIs truncate descriptions); currency conversion uses a dated, static rate table so any chart can be reproduced later; salaries outside a plausible band are counted in an audit rather than silently dropped; and Indonesian postings rarely advertise salary โ€” all stated openly rather than papered over.