Inspiration

Dengue is a recurring threat in Singapore: in the 2020 outbreak, weekly cases peaked at close to 1,800. NEA's inspection teams have limited hours each week, and the public data shows where clusters are active right now, but not which nearby neighbourhoods to check next or how much effort the coming month deserves.

We wanted to build something an inspection planner could open on a Monday morning and get a clear answer to two questions: how urgent are the next four weeks, and where should my team go first?

What it does

DengueRadar is a public dashboard that produces a ranked dengue inspection list for Singapore, refreshed automatically every day.

  • Forecast ("when"): a LightGBM model predicts island-wide weekly dengue cases 4 weeks ahead, and labels the outlook Rising, Stable or Falling.
  • Ranking ("where"): every residential URA subzone gets a transparent risk score from its distance to active clusters, recent rainfall and temperature, weighted by how many seniors and children live there.
  • The forecast sets how wide the net is: when the outlook is Rising, the top 20% of subzones are flagged High instead of the top 10%.

For each subzone \(i\), with active clusters \(c\) at distance \(d_{ic}\) km:

$$\text{spread}_i = \sum_{c} \text{cases}_c \cdot e^{-d_{ic}}$$

$$\text{risk}_i = 0.6\,\text{spread}_i + 0.3\,\text{rain}_i + 0.1\,\text{temp}_i$$

$$\text{priority}_i = \text{risk}_i \times (\text{residents aged 65+} + \text{residents under 15})$$

where spread, rain and temp are each converted to a 0 to 1 percentile rank across subzones.

Officers can click any subzone to see why it is ranked where it is, set their team's capacity to get a list of exactly that length, adjust the risk weights and watch the map recompute, and export the list as a CSV or a printable A4 sheet.

How we built it

  • Data: all real and public. Active clusters from NEA's cluster map feed, weekly cases from the MOH bulletin and NEA, rainfall and temperature from about 90 weather stations via data.gov.sg, historical Changi weather from MSS, subzone boundaries from URA and resident age groups from SingStat.
  • ML: LightGBM trained on weekly cases from 2012 to 2019, with lagged case counts, rainfall and temperature lagged 2 to 8 weeks, and seasonality. The target is \(\log(1 + \text{cases}_{t+4})\).
  • Evaluation: a strict time-based split, tested on 353 unseen weeks from 2020 to 2026, always compared against two baselines: persistence ("same as this week") and seasonal naive ("same week last year").
  • Pipeline: Python (pandas, GeoPandas) computes distances in the SVY21 projection and writes GeoJSON. A GitHub Actions job reruns everything daily and redeploys.
  • Frontend: React, TypeScript, Vite, Tailwind, Leaflet and Recharts, hosted on GitHub Pages with no backend.
  • Quality: 20 automated tests, including one that tampers with all future data and checks that no model feature changes, to prove there is no data leakage.

Challenges we ran into

  • The official case dataset stops at 2022. We found that NEA's dengue page embeds the full weekly series up to the current week, and used that to fill the gap. The two sources differ by about 9 cases a week where they overlap.
  • The open cluster file lags NEA's website by about a week. It listed closed clusters and missed new ones. We traced the feed behind NEA's own cluster map and switched to it, keeping the open file as a fallback with a visible warning.
  • Our model lost to the simplest baseline. The 2020 and 2022 outbreaks peaked at about twice the highest level in the training years, and tree models cannot predict values beyond what they have seen.
  • Patchy weather stations. 15 of 90 rainfall stations were missing more than 10% of days, so each subzone now uses the nearest station with enough coverage, and the skipped stations are listed on the site.

Accomplishments that we're proud of

-Honest evaluation. On unseen weeks our model's average error was 115 cases a week, against 88 for persistence and 336 for seasonal naive. We publish this on the site instead of hiding it. What the model does add is a direction call: it correctly said "up" or "down" in 59% of test weeks, and 73% of outbreak weeks, which persistence cannot do at all.

  • Nothing is simulated. Every number on the site comes from a real, linked public source.
  • Explainable by design. Every rank comes with a plain-English reason built from the actual numbers, and the formula is on the About page.
  • It runs itself. The site refreshes daily with no server and no manual steps.

What we learned

  • A simple baseline is hard to beat for epidemic forecasting, and comparing against one is the only way to know whether a model is useful.
  • Data freshness matters as much as modelling. Two of our biggest accuracy gains came from finding better sources, not from tuning.
  • Transparency builds more trust than a black box: a rule-based index that officers can inspect and adjust is easier to act on than an unexplained score.
  • Data leakage is easy to introduce by accident, so we test for it automatically.

What's next for DengueRadar: Forecasting Where Dengue Strikes Next

  • Validate the ranking against where new clusters actually appear in the following weeks, and tune the weights from that evidence.
  • A true subzone-level forecast, using historical cluster locations, so the "where" is predicted and not only ranked.
  • Better outbreak forecasting: add serotype surveillance data and model the change in cases, so the model can extrapolate beyond past peaks.
  • Model interventions such as Project Wolbachia release areas.
  • Pilot with real users: get feedback from vector control officers and town councils on the inspection list workflow.

Built With

Share this project:

Updates

Submission history