如果你是城市规划师,正在找开源GIS工具来改进你城市规划的工作流程吗?或者你是一名GIS爱好者,对城市发展有兴趣并且愿意做出贡献?
如果你和其他很多规划师一样,你可能考虑过创建工具来自动化常见城市分析任务,但不知道从哪里开始。
那么,这里有5个项目们,包括从初学者到高级的开源GIS项目,你试着建一建。这些项目使用免费、开源的工具,并能为你提供解决实际城市规划问题的实用方法。
记得:最棒的项目是解决真正的难题。这些项目里,每个都应对实际的挑战,城市规划师遇到的挑战,既实用又有教育意义。
1) 步行评分计算器(入门级)想知道不同社区的步行方便程度如何吗?这个工具会根据配套设施的便利性、道路连接性以及人行设施来评估步行得分。
你需要的工具:
- OSMnx(用于街道网络)
- GeoPandas(用于空间)
- OpenStreetMap 数据(免费获取的地理数据)
import osmnx as ox
import geopandas as gpd
import pandas as pd
from shapely.geometry import Point, box
def calculate_walkability_score(location, radius=1000):
"""
计算某个地点基于以下因素的步行评分:
- 步行距离内的设施数量
- 街道网络密度
- 交叉点密度
"""
# 下载街道网络并获取设施
G = ox.graph_from_point(location, dist=radius, network_type='walk')
# 从 OSM 获取设施
amenities = ox.geometries_from_point(
location,
tags={'amenity': True},
dist=radius
)
# 计算指标
area = radius * radius * 3.14159 / 1000000 # km²
# 街道密度 (km/km²)
edge_lengths = ox.utils_graph.get_route_edge_attributes(G, 'length')
street_density = sum(edge_lengths) / 1000 / area
# 交叉点密度
nodes, edges = ox.graph_to_gdfs(G)
intersection_density = len(nodes[nodes.street_count > 1]) / area
# 设施评分
amenity_score = len(amenities) / area
# 计算最终评分(加权平均)
walkability_score = (
0.4 * normalize(street_density) +
0.4 * normalize(intersection_density) +
0.2 * normalize(amenity_score)
)
return walkability_score, {
'street_density': street_density,
'intersection_density': intersection_density,
'amenities_per_sqkm': amenity_score
}
def normalize(value, min_val=0, max_val=100):
"""
将值归一化到 0-100 的区间内
"""
return min(100, max(0, (value - min_val) / (max_val - min_val) * 100))
这个工具提供了一个衡量邻里步行便利性的量化指标。你可以添加更多因素,比如人行道、街道宽度或当地的人口特征,来让工具更全面。
2) 绿色空间分析工具(初级)城市生活的质量至关重要。此工具分析各社区公园和绿地的分布及可达性。
所需工具或库:
- GeoPandas(用于空间分析的库)
- OpenStreetMap 地图数据
- Folium(用于创建交互式地图的库)
import geopandas as gpd
import folium
from shapely.ops import unary_union
import numpy as np
def analyze_green_spaces(city_boundary, population_data):
"""
分析绿地的分布和可达性
"""
# 从OSM加载绿地数据
green_spaces = ox.geometries_from_place(
city_boundary,
tags={'leisure': ['park', 'garden'], 'landuse': ['grass', 'forest']}
)
# 为每个社区计算指标
results = []
for idx, neighborhood in population_data.iterrows():
# 计算绿地面积
neighborhood_green = gpd.clip(green_spaces, neighborhood.geometry)
green_area = neighborhood_green.area.sum()
# 计算可达性(即人口中在绿地400米范围内的比例)
buffer = neighborhood_green.geometry.buffer(400)
accessible_area = unary_union(buffer)
accessibility = (
neighborhood.geometry.intersection(accessible_area).area /
neighborhood.geometry.area
) * 100
results.append({
'neighborhood': neighborhood.name,
'green_space_area': green_area,
'green_space_per_capita': green_area / neighborhood.population,
'accessibility_score': accessibility
})
return pd.DataFrame(results)
def create_green_space_map(analysis_results, city_geometry):
"""创建绿地分析的交互式地图"""
m = folium.Map(location=city_geometry.centroid.coords[0], zoom_start=12)
# 添加分段填充图层
folium.Choropleth(
data=analysis_results,
columns=['neighborhood', 'green_space_per_capita'],
key_on='feature.properties.neighborhood',
fill_color='YlOrRd',
legend_name='人均绿地面积(平方米)'
).add_to(m)
return m
使用历史上的卫星照片和建筑图,跟踪并可视化您的城市是怎样随着时间变化的。
准备工作:
- Rasterio(用于处理卫星图像)
- GeoPandas
- Microsoft Building Footprints(微软建筑轮廓数据,开源数据)
- Scikit-learn(用于数据分析中的模式识别)
import rasterio
import geopandas as gpd
from sklearn.cluster import DBSCAN
import numpy as np
from datetime import datetime
def analyze_urban_growth(building_footprints, years_range):
"""
根据建筑的建造日期来分析城市增长模式。
"""
# 划分分析需要的时间段
gdf = gpd.read_file(building_footprints)
gdf['period'] = pd.cut(gdf['year_built'],
bins=years_range,
labels=[f'{y}-{y+10}' for y in years_range[:-1]])
# 分析增长模式
results = []
for period in gdf['period'].unique():
period_buildings = gdf[gdf['period'] == period]
# 计算密度聚类
coords = np.vstack(period_buildings.geometry.apply(
lambda x: [x.centroid.x, x.centroid.y]
))
clustering = DBSCAN(eps=0.003, min_samples=5).fit(coords)
# 计算相关指标
results.append({
'period': period,
'new_buildings': len(period_buildings),
'total_area': period_buildings.geometry.area.sum(),
'growth_clusters': len(set(clustering.labels_)) - 1, # 将噪声排除在外
'avg_density': len(period_buildings) / period_buildings.unary_union.area
})
return pd.DataFrame(results)
def visualize_growth_patterns(analysis_results, city_boundary):
"""创建城市增长的时间可视化图。"""
fig, ax = plt.subplots(figsize=(15, 10))
for idx, period in enumerate(analysis_results['period']):
period_buildings = analysis_results[analysis_results['period'] == period]
period_buildings.plot(
ax=ax,
color=plt.cm.viridis(idx / len(analysis_results)),
alpha=0.5,
label=period
)
plt.legend(title='时期:')
plt.title('随时间变化的城市增长模式')
return fig
所需工具:
- NetworkX(用于网络分析)
- OSMnx(用于交通网络数据)
- GTFS数据(公共交通时刻表信息)
import networkx as nx
import osmnx as ox
import partridge as ptg
import shapely.ops as ops
def analyze_transit_coverage(city_boundary, gtfs_path):
"""
分析城市公共交通覆盖和服务盲区
"""
# 加载GTFS数据
feed = ptg.load_feed(gtfs_path)
# 创建公交网络
stops = feed.stops
stops_gdf = gpd.GeoDataFrame(
stops,
geometry=gpd.points_from_xy(stops.stop_lon, stops.stop_lat)
)
# 计算服务范围(500米步行距离)
stop_buffers = stops_gdf.geometry.buffer(500)
service_area = ops.unary_union(stop_buffers)
# 确定未覆盖的区域
city_area = gpd.read_file(city_boundary)
gaps = city_area.geometry.difference(service_area)
# 计算交通可达性
population_data = gpd.read_file('population_data.geojson')
results = {
'total_stops': len(stops),
'覆盖率百分比': (service_area.area / city_area.geometry.area) * 100,
'人口覆盖': calculate_population_served(
population_data,
service_area
),
'服务盲区列表': gpd.GeoDataFrame(geometry=[gaps])
}
return results
def calculate_service_frequency(feed, stop_id):
"""计算每个站点的平均服务频率"""
stop_times = feed.stop_times[feed.stop_times.stop_id == stop_id]
trips_per_day = len(stop_times.trip_id.unique())
return trips_per_day
5) 高级城市热岛现象分析器(高级版)
利用卫星图像、土地使用数据资料和温度测量来识别并分析城市热岛现象。
你需要的东西:
— Rasterio(用于卫星图像)
— Earth Engine Python API(用于Landsat数据)
— GeoPandas
— Scikit-learn(进行空间分析)
import ee
import rasterio
import numpy as np
from sklearn.ensemble import RandomForestRegressor
def calculate_temperature_stats(landsat_collection, boundary):,
"""计算来自Landsat影像的温度统计"""
# 转换为摄氏度并计算统计量
temp_image = landsat_collection.mean() \
.multiply(0.00341802).add(149.0) \
.subtract(273.15) # 转换为摄氏度
return temp_image.reduceRegion(
reducer=ee.Reducer.percentile([10, 50, 90]),
geometry=boundary,
scale=30
)
def identify_heat_hotspots(temp_data, threshold):,
"""确定显著更高温度的区域"""
# 使用局部Moran's I来识别集群
weights = pysal.lib.weights.Queen.from_dataframe(temp_data)
moran_loc = pysal.explore.esda.moran.Moran_Local(
temp_data.temperature,
weights
)
# 确定显著热点
hotspots = temp_data[
(moran_loc.p_sim < 0.05) &
(temp_data.temperature > temp_data.temperature.quantile(threshold))
]
return hotspots
def analyze_heat_islands(city_boundary, date_range):
"""使用Landsat数据和土地利用数据来分析城市热岛效应"""
# 初始化地球引擎服务
ee.Initialize()
# 加载Landsat地表温度数据
landsat = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2') \
.filterBounds(city_boundary) \
.filterDate(date_range[0], date_range[1]) \
.select('ST_B10') # 地表温度波段
# 加载土地利用数据
landuse = gpd.read_file('landuse.geojson')
# 计算温度统计
temp_stats = calculate_temperature_stats(landsat, city_boundary)
# 分析土地利用与温度的关系
heat_analysis = analyze_heat_patterns(temp_stats, landuse)
# 识别热点区域
hotspots = identify_heat_hotspots(temp_stats, threshold=0.9)
return {
'temperature_stats': temp_stats,
'heat_analysis': heat_analysis,
'hotspots': hotspots
}
def calculate_temperature_stats(landsat_collection, boundary):
"""计算来自Landsat影像的温度统计"""
# 转换为摄氏度并计算统计量
temp_image = landsat_collection.mean() \
.multiply(0.00341802).add(149.0) \
.subtract(273.15) # 转换为摄氏度
return temp_image.reduceRegion(
reducer=ee.Reducer.percentile([10, 50, 90]),
geometry=boundary,
scale=30
)
def identify_heat_hotspots(temp_data, threshold):
"""确定显著更高温度的区域"""
# 使用局部Moran's I来识别集群
weights = pysal.lib.weights.Queen.from_dataframe(temp_data)
moran_loc = pysal.explore.esda.moran.Moran_Local(
temp_data.temperature,
weights
)
# 确定显著热点
hotspots = temp_data[
(moran_loc.p_sim < 0.05) &
(temp_data.temperature > temp_data.temperature.quantile(threshold))
]
return hotspots
每个项目都使用开源工具和公开数据,非常适合周末做的小项目,这些项目都可逐渐发展成为大型项目。它们解决真实的都市规划问题,同时教会大家实用的地理信息系统 (GIS) 和编程技巧。
想把这些项目继续推进下去吗?可以考虑以下几点:
- 用Streamlit或Dash添加交互式的网页界面
- 引入更多数据来源,如人口普查数据或本地调查
- 使用Python的报表库自动生成报告
- 添加机器学习模型来进行预测分析
- 把你的改进贡献给开源社区吧!
记住,这些项目只是一个开始。你可以根据你城市的具体需求和难题来调整它们。编程愉快!
免费关注我,获取新文章更新通知。