GISNerd

Pasco School Safety Proximity Analysis

Disclaimer:
This project and the data used are strictly for demonstration and coding exercise purposes. They should not be used for any real analysis or decision-making.

View Interactive Map

Project Overview

This project demonstrates an end-to-end GIS workflow that examines the proximity of schools to emergency services (police and fire stations) in Pasco County. Originally, the focus shifted to a more comprehensive approach:


Project Phases

Phase 1: Planning & Data Collection

Note: The data are for demonstration only and should not be used for any critical decisions.

Phase 2: Data Preparation & Spatial Analysis (Pivot)

Example Code Snippet: Generating Buffers and Counting Stations

# Create a 1-mile buffer for every school and attach the school name
buffer_distance_meters = 1 * 1609.34
schools['buffer'] = schools.geometry.buffer(buffer_distance_meters)

# Use the appropriate identifier column (e.g., 'NAME' or 'name')
id_col = 'NAME' if 'NAME' in schools.columns else 'name'
school_buffers = schools[[id_col, 'buffer']].copy()
school_buffers = school_buffers.rename(columns={id_col: 'school_id', 'buffer': 'geometry'})
school_buffers = school_buffers.set_geometry('geometry')

# Perform spatial join to count nearby police stations
police_in_buffer = gpd.sjoin(police, school_buffers, how='inner', predicate='within')
police_counts = police_in_buffer.groupby('school_id').size().reset_index(name='police_count')

# Similarly for fire stations
fire_in_buffer = gpd.sjoin(fire, school_buffers, how='inner', predicate='within')
fire_counts = fire_in_buffer.groupby('school_id').size().reset_index(name='fire_count')

# Merge counts back into the buffers GeoDataFrame
school_buffers = school_buffers.merge(police_counts, on='school_id', how='left')
school_buffers = school_buffers.merge(fire_counts, on='school_id', how='left')
school_buffers['police_count'] = school_buffers['police_count'].fillna(0).astype(int)
school_buffers['fire_count'] = school_buffers['fire_count'].fillna(0).astype(int)

Phase 3: Code-Based Workflow Documentation

Phase 4: Network Analysis with OSMnx

Example Code Snippet: Isochrone Generation

def generate_isochrone(G, center_node, travel_time_limit):
    travel_times = nx.single_source_dijkstra_path_length(G, center_node, weight='travel_time')
    reachable_nodes = [node for node, t in travel_times.items() if t <= travel_time_limit]
    nodes = ox.graph_to_gdfs(G, nodes=True, edges=False)
    reachable_points = nodes.loc[reachable_nodes]['geometry']
    multipoint = MultiPoint(list(reachable_points))
    return multipoint.convex_hull if not multipoint.is_empty else None

Phase 5: WebGIS Application & Dashboard Development

These dashboards deliver quantitative insights.

Example Code Snippet: Basic Leaflet Map Initialization

<script>
  var map = L.map('map').setView([28.2465, -82.6925], 11);
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 19,
    attribution: '&copy; OpenStreetMap contributors'
  }).addTo(map);
</script>

Conclusion

This pivot refines the approach by generating buffers for every school and incorporating spatial joins to count nearby emergency services, alongside generating network isochrones for a realistic measure of accessibility. The result is a robust, integrated GIS workflow that demonstrates advanced spatial analysis techniques and delivers interactive, dashboard-driven insights into school safety proximity in Pasco County.