project — GIS 5571, multi-criteria site suitability

Ranking Minnesota's best sites for utility-scale solar - and being upfront about the ranking's limits.

A weighted GIS model combining land cover, parcel size, slope, aspect, and road proximity into a single suitability score for candidate solar sites statewide, built under a real semester deadline with real unresolved questions about how sound the final ranking actually is.

DataNLCD land cover, 30m DEM, opt-in county parcels, TIGER/Line roads
ToolsArcPy, ArcGIS Pro, Spatial Analyst
Coverage59 of 87 Minnesota counties
The top-ranked parcel from the analysis, shown on a street map near Audubon, Minnesota
fig. 01the #1-ranked parcel, a real ~30+ acre property just north of Audubon, MN

The goal

Most solar suitability resources I looked at before starting combined only a couple of factors - elevation and aspect, typically. The goal here was to combine more of what actually matters for siting a utility-scale array: available acreage, slope, aspect, land cover, and proximity to roads and transmission infrastructure. I also wanted the whole pipeline automated end to end.

Neither of those fully happened. Transmission line proximity and solar irradiation data were part of the original plan and never made it into the final model - there simply wasn't time. And the land cover reclassification step, which I'd hoped to run entirely in ArcPy, kept failing for reasons I still don't fully understand, so I ended up doing that one step by hand in ArcGIS Pro's interface instead of in code.

The approach

Two hard constraints come first: parcels have to be at least 30 acres, and land cover has to fall into a suitable class (developed open space, shrub/scrub, grassland, pasture, or cultivated crops). Everything that passes both filters gets scored on three weighted factors - percent suitable land cover, percent low-slope area, percent south-facing area - minus a penalty for parcels with a lot of major road running through them.

Data flow diagram showing the full pipeline from raw NLCD, parcel, roads, and DEM data through to the top 10 solar site layer
fig. 02 — the full pipeline, from raw data to ranked output

The actual results

Here's the real output table for the top 10 ranked parcels:

Attribute table showing the top 10 ranked parcels with their suitability scores
fig. 03 — top 10 parcels by final_score, with every scoring field visible

Two things stand out looking at this honestly, rather than just presenting it as a clean top-10 list:

What I'd actually change

From my own reflection on this project, written right after finishing it:

On "is this mathematically sound"

Short answer: not fully validated yet, and I think it's more useful to say that directly than to imply otherwise. The weights (45% land cover, 30% slope, 10% aspect, minus a 15% road penalty) reflect a reasonable but subjective prioritization, not a value derived from literature or a formal method like pairwise AHP comparison. The notebook now includes a sensitivity analysis that tests how much the top-10 result actually depends on that specific choice of weights - the real next step is running it against the actual output and reporting what it finds, rather than presenting one ranking as the final word.

Get the files

Notebook (.ipynb)
full ArcPy pipeline, cleaned up and bug-fixed, includes the sensitivity analysis
view on GitHub
Full writeup (PDF)
data sources, data flow diagram, and reflection questions
download