پرش به محتویات

پیاده‌سازی مدل 2SFCA در پایتون

Sample Data 2SFCA Notebook YouTube

در جلسه3 ، ابتدا به معرفی مدل 2SFCA (Two-Step Floating Catchment Area) پرداختیم. این مدل ابزاری اساسی در شهرسازی است که برای ارزیابی دسترسی به خدمات عمومی، به‌ویژه خدمات بهداشتی و درمانی، طراحی شده است. هدف اصلی مدل 2SFCA شناسایی نابرابری‌های فضایی در دسترسی به منابع و خدمات شهری است. در ابتدا، این مدل میزان دسترسی به خدمات در هر منطقه را محاسبه می‌کند؛ به این صورت که هر مکان خدماتی، مانند بیمارستان یا مدرسه، به جمعیت‌های اطراف خود در یک شعاع خاص، که معمولاً به‌طور استاندارد مشخص می‌شود، ارزیابی می‌شود. سپس، این دسترسی‌ها به‌طور تجمیعی برای هر نقطه جمعیتی محاسبه می‌شود و یک امتیاز کلی از دسترسی به خدمات برای هر ناحیه مشخص می‌شود. در نهایت، این مدل کمک می‌کند تا مناطقی که دسترسی کمتری به خدمات دارند شناسایی و در آن‌ها اقدامات مناسب جهت بهبود دسترسی انجام شود.

مراحل پیاده‌سازی در پایتون

برای انجام این کار، ابتدا کتابخانه‌های مورد نیاز را در فایل نوت‌بوک فراخوانی می‌کنیم. همان‌طور که پیش‌تر توضیح داده شد، کتابخانه‌های Pandas و GeoPandas برای کار با داده‌های جدولی و مکانی ضروری هستند. علاوه بر این دو، کتابخانه‌ی Matplotlib برای ترسیم نقشه‌ها و نمودارها و OSMnx برای دریافت داده‌های مکانی از OpenStreetMap استفاده می‌شود.

import pandas as pd
import geopandas as gpd
import matplotlib.pyplot as plt
import osmnx as ox
````

در این مرحله، ابتدا دادههای مکانی مورد نیاز را از فایلهای Shapefile بارگذاری میکنیم. فایل نخست شامل مرزهای محلههای شهر تهران است و فایل دوم دادههای بلوکهای جمعیتی را در بر دارد. این دادهها در قالب دو GeoDataFrame به نامهای `gdf_hoods` و `gdf_popblock` ذخیره میشوند.

```python
gdf_hoods = gpd.read_file(r"data\mahallat.shp")
gdf_popblock = gpd.read_file(r"data\pop\tehran_popblocks_95.shp")

پس از بارگذاری داده‌ها، با استفاده از دستور plot() می‌توان یک نمای اولیه از نقشه را مشاهده کرد تا از صحت داده‌ها اطمینان حاصل شود.

gdf_hoods.plot()

در این مرحله، داده‌های مکانی ما آماده هستند اما برای انجام محاسبات فضایی دقیق، باید از یک سیستم مختصات متریک استفاده کنیم. همان‌طور که پیش‌تر توضیح داده شد، داده‌های جغرافیایی معمولاً در سیستم مختصات WGS84 (EPSG:4326) ذخیره می‌شوند که بر حسب درجه است و برای محاسبات فاصله مناسب نیست. بنابراین، لازم است تا سیستم مختصات آن‌ها را به یک CRS متریک (بر حسب متر) تغییر دهیم. برای محدوده‌ی تهران معمولاً از سیستم مختصات UTM Zone 39N (EPSG:32639) استفاده می‌شود.

gdf_hoods = gdf_hoods.to_crs(epsg=32639)
gdf_popblock = gdf_popblock.to_crs(epsg=32639)

تا این مرحله، داده‌های جمعیتی و محدوده‌های شهری آماده شده‌اند. در گام بعدی لازم است داده‌های مربوط به بیمارستان‌ها را به‌عنوان مراکز عرضه‌ی خدمات درمانی به مدل اضافه کنیم. یکی از مزیت‌های بزرگ کتابخانه‌ی OSMnx این است که امکان دریافت مستقیم داده‌های مکانی از پایگاه داده‌ی OpenStreetMap را فراهم می‌کند. برای مثال، با استفاده از قطعه کد زیر می‌توان موقعیت مکانی تمام بیمارستان‌های شهر تهران را دریافت کرد:

place = "Tehran, Iran"
tags = {'amenity': 'hospital'}
hospitals = ox.features_from_place(place, tags)

داده‌های دریافتی ممکن است شامل انواع مختلف هندسه‌ها (نقطه، خط و چندضلعی) باشند. برای تحلیل دقیق‌تر، معمولاً از بیمارستان‌هایی استفاده می‌شود که به صورت چندضلعی (Polygon) ثبت شده‌اند، زیرا این نوع داده مرز واقعی فضاهای خدماتی را بهتر نمایش می‌دهد. برای فیلتر کردن این داده‌ها، می‌توان از دستور زیر استفاده کرد:

gdf_hospitals = hospitals[hospitals.geom_type == 'Polygon']

اکنون داده‌های عرضه (بیمارستان‌ها) و تقاضا (جمعیت هر بلوک) آماده هستند و می‌توان وارد بخش اصلی محاسبه‌ی شاخص دسترسی شد. در مدل 2SFCA، محاسبه در دو مرحله انجام می‌شود. در مرحله‌ی نخست، برای هر مرکز خدماتی (در اینجا بیمارستان)، جمعیت موجود در محدوده‌ای با شعاع مشخص (برای مثال ۱۵۰۰ متر) محاسبه شده و نسبت ظرفیت مرکز به جمعیت پیرامون آن (نسبت عرضه به تقاضا) به دست می‌آید. سپس در مرحله‌ی دوم، برای هر واحد جمعیتی (بلوک یا محله)، مجموع نسبت‌های دسترسی تمام بیمارستان‌هایی که در شعاع ۱۵۰۰ متری آن قرار دارند محاسبه می‌شود. این مقدار نشان‌دهنده‌ی شاخص دسترسی هر بلوک به خدمات درمانی است.

برای محاسبه‌ی مرحله‌ی نخست، ابتدا باید فاصله‌ی میان نقاط جمعیتی و مراکز خدماتی اندازه‌گیری شود. سپس جمعیت موجود در محدوده‌ی هر بیمارستان محاسبه می‌شود. در این مثال از متد distance() برای اندازه‌گیری فاصله‌ی میان مرکز هندسی (centroid) هر بلوک و بیمارستان استفاده می‌کنیم.

radius = 1500
Rj = []
for idx, row in gdf_hospitals.iterrows():
    catchment = gdf_popblock[gdf_popblock.geometry.centroid.distance(row.geometry.centroid) < radius]
    demand_sum = catchment['POPULATION'].sum()
    if demand_sum > 0:
        ratio = row.geometry.area / demand_sum
    else:
        ratio = 0
    Rj.append(ratio)
gdf_hospitals['Rj'] = Rj

در این قطعه کد، ابتدا برای هر بیمارستان محدوده‌ی نفوذ (Catchment Area) با شعاع ۱۵۰۰ متر تعریف می‌شود، سپس جمعیت موجود در آن محدوده محاسبه و نسبت عرضه به تقاضا (Rj) تعیین می‌گردد. این مقدار در جدول ویژگی‌های هر بیمارستان ذخیره می‌شود.

در مرحله‌ی دوم مدل 2SFCA، برای هر بلوک جمعیتی، مجموع مقادیر Rj بیمارستان‌هایی که در محدوده‌ی نفوذ آن قرار دارند محاسبه می‌شود. به این ترتیب شاخص نهایی دسترسی هر بلوک (r2sfca) به دست می‌آید:

r2sfca = []
for idx, row in gdf_popblock.iterrows():
    catchment = gdf_hospitals[gdf_hospitals.geometry.centroid.distance(row.geometry.centroid) < radius]
    supply_sum = catchment['Rj'].sum()
    r2sfca.append(supply_sum)
gdf_popblock['r2sfca'] = r2sfca

نتیجه‌ی این محاسبات به ما یک لایه‌ی مکانی می‌دهد که مقدار شاخص دسترسی برای هر بلوک جمعیتی در آن مشخص شده است. برای نمایش بصری این شاخص، می‌توان از متد plot() در GeoPandas استفاده کرد تا نقشه‌ی نهایی توزیع فضایی دسترسی ترسیم شود:

gdf_popblock.plot(column='r2sfca', cmap='YlOrRd', legend=True)
plt.title("Accessibility to Hospitals in Tehran (2SFCA)")
plt.show()

نمایش نقشه و ذخیره نتایج

در این مرحله، پس از انجام محاسبات مربوط به شاخص دسترسی (r2sfca)، می‌خواهیم این نتایج را به‌صورت بصری نمایش دهیم و آن‌ها را ذخیره کنیم. در اینجا دو روش برای ذخیره نقشه‌ها وجود دارد: نقشه‌ی ثابت (PNG) و نقشه‌ی تعاملی (HTML).

  1. نقشه ثابت (PNG)

برای ذخیره نقشه در فرمت ثابت، از متد savefig در کتابخانه‌ی matplotlib استفاده می‌کنیم. در این مرحله، نقشه‌ای که بر اساس شاخص r2sfca ترسیم شده را ذخیره می‌کنیم.

fig = agg_hoods.plot(column='r2sfca', cmap='Spectral')
plt.savefig('r2sfca.png')

این کد ابتدا یک نقشه از داده‌ها ترسیم کرده و سپس آن را با نام r2sfca.png در فرمت تصویری ذخیره می‌کند. این تصویر می‌تواند برای گزارش‌ها یا چاپ استفاده شود.

  1. نقشه تعاملی (HTML)

اگر بخواهیم نقشه به‌صورت تعاملی باشد تا کاربر بتواند به‌راحتی بر روی آن زوم کرده و جزئیات بیشتری را مشاهده کند، از قابلیت‌های کتابخانه‌ی folium در GeoPandas استفاده می‌کنیم. این قابلیت به‌طور خودکار به ما این امکان را می‌دهد که نقشه را در قالب HTML ذخیره کنیم.

m = agg_hoods.explore(column='r2sfca', cmap='Spectral')
m.save('r2sfca.html')

در اینجا، با استفاده از متد explore(), یک نقشه تعاملی بر اساس داده‌ها ساخته می‌شود و با دستور save() این نقشه در فرمت HTML ذخیره می‌شود. این فایل HTML می‌تواند در مرورگر وب باز شود و به کاربران امکان تعامل با نقشه را بدهد. برای استفاده از پالت‌های رنگی در Matplotlib، می‌توانید از رنگ‌های پیش‌فرض موجود در این کتابخانه استفاده کنید. این پالت‌ها به‌ویژه برای تحلیل‌های مکانی و ایجاد نقشه‌های طبقه‌بندی‌شده بسیار مناسب هستند. در Matplotlib برخی از پالت‌های محبوب برای مصارف مختلف عبارتند از:

پالت‌های رنگی Matplotlib:

Viridis

یکی از محبوب‌ترین پالت‌ها که رنگ‌ها از زرد به سبز و سپس به آبی تغییر می‌کنند.

مناسب برای نمایش داده‌های پیوسته، زیرا تغییرات تدریجی را به خوبی نشان می‌دهد.

این پالت معمولاً برای نشان دادن مقادیر با دامنه‌های متنوع مناسب است.

Plasma

مشابه به پالت Viridis، اما رنگ‌ها شدیدتر و با کنتراست بالاتری طراحی شده‌اند.

این پالت به دلیل روشنایی زیاد، برای نشان دادن مقادیر مهم یا با تفاوت‌های قابل توجه مناسب است.

Inferno

پالت رنگی با رنگ‌های گرم که از قرمز به زرد تغییر می‌کنند.

مناسب برای نمایش مقادیر با دامنه‌های بالا و برای مواقعی که نیاز به نشان دادن تفاوت‌های شدید در مقادیر دارید.

YlOrRd

طیف رنگی از زرد تا قرمز است.

معمولاً برای داده‌هایی استفاده می‌شود که دامنه‌های بزرگ دارند. رنگ قرمز نشان‌دهنده مقادیر بالاتر است و رنگ زرد برای مقادیر پایین‌تر استفاده می‌شود.

Coolwarm

این پالت ترکیبی از رنگ‌های آبی و قرمز است.

معمولاً برای داده‌های دوگانه یا تقسیم‌بندی‌شده مناسب است و می‌تواند تفاوت‌ها را بین دو دسته یا متغیر به خوبی نمایش دهد.

برای مشاهده کامل این پالت‌ها و استفاده از آن‌ها در پروژه‌های خود، می‌توانید به مستندات رسمی Matplotlib مراجعه کنید:

https://matplotlib.org/stable/users/explain/colors/colormaps.html