Methodology & data

How every score is worked out

110

automatic tests

53 on the data, 57 on the website

0.94

ranking stability

1,000 random weightings, 1 = identical

0.93

lowest when one ingredient is removed

still almost the same ranking

5

decimals

the website's maths must match Python's

How each score is calculated

1

Concentration (Gini)

Are visits spread across the country, or piled into a few states? 0 = every state gets the same. 1 = one state gets everything.

  1. 1Sort the 16 states from fewest visitors to most.
  2. 2Give them weights from −15 (smallest) up to +15 (biggest), in steps of 2.
  3. 3Multiply each state's visitors by its weight and add everything up.
  4. 4Divide by (16 × total visitors).

Malaysia 2025

Gini = 0.294. The top 3 (Selangor, Kuala Lumpur, Perak) take 32.8% of 290.1M visits. The 8 least-visited states share only 29.8%. The Lorenz curve is the same thing drawn: the further it sags below the diagonal, the more uneven.
2

Opportunity score

Which states have a lot to offer but few visitors? Opportunity = what it can offer − how visited it already is.

  1. 1Score every ingredient from 0 to 100: (state − lowest state) ÷ (highest − lowest) × 100.
  2. 2Counts (rooms, attractions, visitor measures) are logged first, so Kuala Lumpur's size does not flatten everyone else.
  3. 3Offer = average of 7 scores. Visited = average of 3. Equal weights unless you move the sliders.
  4. 4Opportunity = Offer − Visited. Above 0 is untapped, below 0 is crowded.

Johor 2025

Spare capacity (100 - occupancy %): (45.8 − 23.7) ÷ (60.6 − 23.7) × 100 = 59.9Accommodation supply (rooms)84.5Spare capacity (100 - occupancy %)59.9Spend per visitor (RM)43.5Average length of stay (nights)10.2Household basic amenities access (%)97.2Attractions, nature & heritage sites (OSM)91.8JomRasa Experience Score26.5Offer (average)59.1Share of national domestic visitors74.3Visitors per resident (intensity)0.0Visitors per km2 (density)24.7Visited (average)33.059.1 − 33.0 = +26.1, rank 2 of 16.
3

Bottleneck Diagnoser

What holds a state back: getting there (access), being known (awareness), or places to stay (amenities)? Four ingredients each.

  1. 1For each ingredient, find the typical state: the median of the 16.
  2. 2Typical spread = the median distance from that median × 1.4826.
  3. 3Distance = (state − median) ÷ typical spread, limited to −3 … +3.
  4. 4Pillar score = 50 + (average of its 4 distances) × 50 ÷ 3. 50 = the typical state.
  5. 5Bottleneck = the lowest pillar, flagged only if it is below 50.

Johor 2025

Tourists from other states (%): (65.2 − 86.4) ÷ 14.3 = -1.48Awareness: average distance -0.57, so 50 + (-0.57 × 16.67) = 40.4Access 41.1 · Awareness 40.4 · Amenities 47.2. Bottleneck: Awareness.
4

Room to grow

How many more visitors can the hotels that already exist take, without building anything?

  1. 1Spare room-nights = rooms × 365 × (75% − occupancy). The ceiling is yours to change in the Simulator.
  2. 2Room-nights one visitor needs = overnight share × paid accommodation share × nights ÷ 2 per room.
  3. 3Extra visitors = step 1 ÷ step 2.

Johor 2025

36,034 × 365 × (75% − 54.2%) = 2,735,701 spare room-nights0.54 × 0.30 × 2.18 ÷ 2 = 0.175 per visitor2,735,701 ÷ 0.175 = 15.6M extra visitors
5

Simulator

What changes if some visitors go to another state instead? A what-if calculator, not a forecast.

  1. 1Visitors moved = the crowded state's visitors × the chosen %.
  2. 2Split them across the destinations. None takes more than its room to grow; the overflow goes to the others.
  3. 3Gained = moved × destination's spend per visitor. Lost = moved × origin's spend per visitor. Net = gained − lost.
  4. 4Gini, top-3 share and hotel occupancy are recalculated.

10% of Selangor to Johor, Sarawak, Sabah

3.6M moved, all fit.RM 1.49bn gained − RM 1.46bn lost = +RM 26MGini 0.294 to 0.287.
6

Traveller scores (JomRasa)

How do real travellers describe each state? The only part that uses AI, and only to label text.

  1. 1A ready-made model (Gemini 2.5 Flash Lite) tags each post from fixed lists: real trip or not, place, topic (1 of 11), negative / mixed / positive.
  2. 2The "real trip?" question is asked twice; a post is kept only on two yeses: 7,561 posts.
  3. 3Negative = 0, mixed = 50, positive = 100. Average per state and topic.
  4. 4Few mentions? The average is pulled towards the national average: (mentions × state average + k × national average) ÷ (mentions + k).
  5. 5Experience Score = average of the adjusted topic scores.

Johor

Safety: only 12 mentions averaging 62.5, adjusted to 50.5.Food: 208 mentions averaging 94.5, adjusted to 93.8 (plenty of evidence, so it hardly moves).Experience Score = 82.0 from 458 posts.

Trip planner

  • Places, eateries and hotels are real listings from Wikivoyage and OpenStreetMap. Descriptions are trimmed, never rewritten.
  • A language model picks and orders places from that list only. Anything not on the list is dropped.
  • Limits like "no pork" or "with kids" are enforced by our code before and after the model answers.
  • Clock times, travel legs and the nearest hotel are calculated by us, never guessed by the model.
  • If the model is down, a rule-based planner takes over: k-means groups sights into days, then the shortest route is found.
  • When to go comes from ten years of daily rainfall (Open-Meteo, 2015-2024) for each town.

Which year each number is from

  • Visitors, where tourists come from, hotel rooms and occupancy are from the year you pick.
  • DOSM publishes state spending only up to 2023. For 2024 and 2025, spend per visitor and nights stayed are the 2023 figures, labelled on screen.
  • Receipts for 2024 and 2025 are therefore estimates. 2023 is the fully matched year.

References

  • Concentration: Gini and Lorenz curve, as used for tourism by Fernández-Morales et al. (2016) and Lau & Koo (2022).
  • Opportunity: normalise-then-average composite index (OECD/JRC Handbook, 2008); visited side follows tourism intensity and density (McElroy & de Albuquerque; Eurostat).
  • Bottleneck Diagnoser: Buhalis's (2000) destination "As". Small samples: empirical-Bayes shrinkage (Efron & Morris, 1975).
  • Optional economic multiplier: Malaysian input-output range 1.20-1.82 (Mazumder et al., 2009). Off by default.

Data sources

SourceUsed forYearsLevelAccessed
DOSM Domestic Tourism Survey 2025 (national workbook)Visitors by state 2018-2025 (Table 9); tourists by origin × destination (Table 10); top destinations & districts (Tables 8A-8B); national key statistics2018-2025State2026-09-17
DOSM Domestic Tourism Survey 2024 (national workbook)2017 visitors by state; 2024 origin × destination matrix2017-2024State2026-09-17
DOSM Domestic Tourism Survey by State 2023 (16 workbooks)Receipts, trips, spend per visitor / trip, length of stay, tourist vs excursionist split, transport mode, accommodation type, NAPIC hotel stock2017-2023State2026-09-17
Tourism Malaysia - Paid Accommodation Survey (public Power BI)Hotels & rooms by state; average occupancy rate by state and quarter; domestic & foreign hotel guests2018 - Q1 2026State2026-09-17
data.gov.my / OpenDOSM - population_stateMid-year population by state2015-2026State2026-09-17
data.gov.my / OpenDOSM - HIES: hh_access_amenities, hh_income_state, hh_poverty_statePiped water, sanitation, electricity access; household income; poverty2016-2024District / state2026-09-17
data.gov.my / OpenDOSM - gdp_state_real_supplyReal GDP by state2016-2025State2026-09-17
data.gov.my - arrivals_soeForeign arrivals by state of entry (context only - entry point, not destination; ends Oct 2024)2020-2024State2026-09-17
geoBoundaries MYS ADM1 (simplified)State boundariescurrentPolygon2026-09-17
OpenStreetMap via Overpass APIAttractions, nature & heritage sites, airports with IATA codes, rail stations - assigned to states by point-in-polygoncurrentPoint2026-09-17
Exa search APIPublic travel blogs, forums and articles per state in Malay, English and Mandarin (TripAdvisor and Google Maps excluded); text passages only, no author datarecentText2026-09-17
YouTube Data API v3Public comments on per-state travel videos; comment text only, no usernames or channel ids storedrecentText2026-09-17

Indicators behind each score

Potential index

  • Accommodation supply (rooms)logTourism Malaysia PAS
  • Spare capacity (100 - occupancy %)Tourism Malaysia PAS
  • Spend per visitor (RM)DOSM DTS by state
  • Average length of stay (nights)DOSM DTS by state
  • Household basic amenities access (%)DOSM HIES / data.gov.my
  • Attractions, nature & heritage sites (OSM)logOpenStreetMap
  • JomRasa Experience ScoreJomRasa

Actual index

  • Share of national domestic visitorslogDOSM DTS
  • Visitors per resident (intensity)logDOSM DTS + population
  • Visitors per km2 (density)logDOSM DTS + area

Pillar · Access

  • Population within reach (distance-decayed)logDOSM population + coordinates
  • Airports with IATA code within 100 kmOpenStreetMap
  • Intercity / commuter rail stationslogOpenStreetMap
  • Traveller sentiment: access & transportJomRasa

Pillar · Awareness

  • Tourists from other states (%)DOSM DTS Table 10
  • Diversity of origin states (1 - HHI)DOSM DTS Table 10
  • Foreign share of hotel guests (%)Tourism Malaysia PAS
  • Online travel mentions collectedlogJomRasa

Pillar · Amenities

  • Rooms per 1,000 overnight touristslogTourism Malaysia PAS + DOSM
  • Rooms per 1,000 residents (Defert-type)logTourism Malaysia PAS + DOSM
  • Household basic amenities access (%)DOSM HIES
  • Traveller sentiment: accommodation, food, cleanlinessJomRasa

Assumptions and limitations

  • Access is proxy-based (distance-decayed population reach, airports with an IATA code within 100 km, rail stations). No open road, flight-frequency or travel-time data exist; great-circle distance understates the sea crossing to Sabah, Sarawak and Labuan.
  • OpenStreetMap coverage is uneven between states; site counts are log-scaled and carry one-seventh of the Potential index by default.
  • Hotel capacity covers registered paid accommodation in Tourism Malaysia's survey; homestays and short-term rentals outside it are not counted, so capacity is conservative.
  • Labuan, Putrajaya and Perlis are very small units; their scores move a lot with small absolute changes. Read them with the sensitivity intervals.
  • JomRasa scores come from public online text, not a representative survey. They are an indicator of traveller experience, never an official statistic.
  • The trip planner covers only towns that travellers have documented on Wikivoyage, and coverage is uneven: Kuala Lumpur, Penang, Johor Bahru and Ipoh are rich, parts of Kelantan, Perlis and Terengganu are thin, especially for food. Opening hours and eateries change; the app says so and links every stop to a map. A short town is given fewer days rather than padded.