Quick Start Guide

5-Minute Tutorial

1. Installation

pip install unsprawl

2. Get Sample Data

unsprawl fetch --limit 5000

This creates a ResaleFlatPrices/ directory with sample data.

3. Run Your First Analysis

CLI:

unsprawl \
  --input "ResaleFlatPrices/Resale flat prices based on registration date from Jan-2017 onwards.csv" \
  --town PUNGGOL \
  --budget 600000 \
  --top 10

Python:

from unsprawl import UnsprawlApp

app = UnsprawlApp()
results = app.process(
    input_path="ResaleFlatPrices/Resale flat prices based on registration date from Jan-2017 onwards.csv",
    town="PUNGGOL",
    budget=600000,
    top_n=10
)

print(results)

4. MRT Accessibility (Default)

By default, the module will use the bundled default MRT exits GeoJSON (if present) and compute accessibility metrics automatically.

from unsprawl import UnsprawlApp

app = UnsprawlApp()
results = app.process(
    input_path="ResaleFlatPrices/Resale flat prices based on registration date from Jan-2017 onwards.csv",
    town="BISHAN",
    budget=800000,
    top_n=10,
)

# Results include Nearest_MRT, Dist_m, Accessibility_Score, and accessibility_score
print(results[["town", "resale_price", "Nearest_MRT", "Accessibility_Score", "valuation_score"]])

If you want to explicitly point at a different MRT catalog:

unsprawl fetch --datasets mrt --mrt-out .data/stations.geojson
results = app.process(
    input_path="ResaleFlatPrices/Resale flat prices based on registration date from Jan-2017 onwards.csv",
    mrt_catalog=".data/stations.geojson",
    town="BISHAN",
    budget=800000,
    top_n=10,
)

To disable accessibility scoring (even if the default MRT file exists), pass an empty string:

results = app.process(
    input_path="ResaleFlatPrices/Resale flat prices based on registration date from Jan-2017 onwards.csv",
    mrt_catalog="",
    town="BISHAN",
)

What’s Next?

Common Use Cases

Find Budget-Friendly Properties

results = app.process(
    input_path="resale.csv",
    budget=450000,
    flat_type="4 ROOM",
    area_min=85,
    area_max=95,
    lease_min=75,
    top_n=20
)

Compare Multiple Towns

app.load_data("resale.csv")  # Load once

punggol = app.process(town="PUNGGOL", top_n=5)
sengkang = app.process(town="SENGKANG", top_n=5)
tampines = app.process(town="TAMPINES", top_n=5)

Export Results

results = app.process(
    input_path="resale.csv",
    town="QUEENSTOWN",
    return_full=True  # Get all results
)

# Export
results.to_csv("undervalued_queenstown.csv", index=False)
results.to_json("undervalued_queenstown.json", orient="records")

Key Concepts

Valuation Score

The valuation score is computed as:

valuation_score = -z_price_efficiency

Where z_price_efficiency is the group-wise Z-score of price efficiency.

Higher scores = More undervalued properties

Price Efficiency

Price efficiency is calculated as:

price_efficiency = resale_price / (floor_area_sqm * remaining_lease_years)

This metric adjusts for both size and remaining lease, making properties comparable.

Accessibility Score

When MRT data is available (default behavior):

accessibility_score = max(0, 10 - 2 * distance_km)

Accessibility adjusts the price efficiency, making well-connected properties more attractive.

Getting Help

  • Documentation: https://unsprawl.github.io/unsprawl/

  • Issues: https://github.com/unsprawl/unsprawl/issues

  • Email: [Your email]