import geopandas as gpd
import matplotlib.pyplot as plt
from cityseer.metrics import layers
from cityseer.tools import graphs, io
= gpd.read_file("data/madrid_streets/street_network.gpkg")
streets_gpd = streets_gpd.explode(reset_index=True)
streets_gpd = io.nx_from_generic_geopandas(streets_gpd)
G = graphs.nx_to_dual(G)
G_dual = io.network_structure_from_nx(G_dual) nodes_gdf, _edges_gdf, network_structure
INFO:cityseer.tools.graphs:Merging parallel edges within buffer of 1.
INFO:cityseer.tools.graphs:Converting graph to dual.
INFO:cityseer.tools.graphs:Preparing dual nodes
INFO:cityseer.tools.graphs:Preparing dual edges (splitting and welding geoms)
INFO:cityseer.tools.io:Preparing node and edge arrays from networkX graph.
INFO:cityseer.graph:Edge R-tree built successfully with 104026 items.
= gpd.read_file("data/madrid_premises/madrid_premises.gpkg")
prems_gpd prems_gpd.head()
index | local_id | local_distr_id | local_distr_desc | local_neighb_id | local_neighb_desc | local_neighb_code | local_census_section_id | local_census_section_desc | section_id | section_desc | division_id | division_desc | epigraph_id | epigraph_desc | easting | northing | geometry | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 10003324 | 1 | CENTRO | 105 | UNIVERSIDAD | 5 | 1091 | 91 | I | hospitality | 56 | food_bev | 561001 | RESTAURANTE | 440181.6 | 4475586.5 | POINT (440181.6 4475586.5) |
1 | 1 | 10003330 | 1 | CENTRO | 105 | UNIVERSIDAD | 5 | 1115 | 115 | R | art_rec_entert | 90 | creat_entert | 900003 | TEATRO Y ACTIVIDADES ESCENICAS REALIZADAS EN D... | 440000.6 | 4474761.5 | POINT (440000.6 4474761.5) |
2 | 2 | 10003356 | 1 | CENTRO | 104 | JUSTICIA | 4 | 1074 | 74 | I | hospitality | 56 | food_bev | 561004 | BAR RESTAURANTE | 440618.6 | 4474692.5 | POINT (440618.6 4474692.5) |
3 | 3 | 10003364 | 1 | CENTRO | 104 | JUSTICIA | 4 | 1075 | 75 | G | wholesale_retail_motor | 47 | retail | 472401 | COMERCIO AL POR MENOR DE PAN Y PRODUCTOS DE PA... | 440666.6 | 4474909.5 | POINT (440666.6 4474909.5) |
4 | 4 | 10003367 | 1 | CENTRO | 106 | SOL | 6 | 1119 | 119 | G | wholesale_retail_motor | 47 | retail | 477701 | COMERCIO AL POR MENOR DE JOYAS, RELOJERIA Y BI... | 440378.6 | 4474380.5 | POINT (440378.6 4474380.5) |
# compute accessibility
= [800, 1600]
distances = layers.compute_accessibilities(
nodes_gdf, prems_gpd
prems_gpd,="division_desc",
landuse_column_label=["retail"],
accessibility_keys=nodes_gdf,
nodes_gdf=network_structure,
network_structure=distances,
distances
)# keep a copy before adding GTFS for comparison
for col in nodes_gdf.columns:
if col.startswith("cc_"):
f"{col}_not"] = nodes_gdf[col] nodes_gdf[
INFO:cityseer.metrics.layers:Computing land-use accessibility for: retail
INFO:cityseer.metrics.layers:Assigning data to network.
INFO:cityseer.data:Assigning 117358 data entries to network nodes (max_dist: 100).
INFO:cityseer.data:Finished assigning data. 198773 assignments added to 24576 nodes.
INFO:cityseer.config:Metrics computed for:
INFO:cityseer.config:Distance: 800m, Beta: 0.005, Walking Time: 10.0 minutes.
INFO:cityseer.config:Distance: 1600m, Beta: 0.0025, Walking Time: 20.0 minutes.
= io.add_transport_gtfs(
network_structure, stops, avg_stop_pairs "data/madrid_gtfs/madrid_metro",
network_structure,
nodes_gdf.crs, )
INFO:cityseer.tools.io:Loading GTFS data from data/madrid_gtfs/madrid_metro
INFO:cityseer.tools.io:Loaded 1272 stops and 2360 stop times
INFO:cityseer.tools.io:Adding GTFS stops to network nodes (with street linking logic).
INFO:cityseer.tools.io:Generating segment durations between stops.
INFO:cityseer.tools.io:Adding GTFS segments to network edges.
INFO:cityseer.graph:Edge R-tree built successfully with 104026 items.
# convert stops to geopandas
= gpd.GeoDataFrame(
stops_gdf
stops,=gpd.points_from_xy(stops["stop_lon"], stops["stop_lat"]),
geometry=4326, # Adjust the CRS to suit your data if needed
crs
)= stops_gdf.to_crs(streets_gpd.crs.to_epsg())
stops_gdf stops_gdf
stop_id | stop_code | stop_name | stop_desc | stop_lat | stop_lon | zone_id | stop_url | location_type | parent_station | stop_timezone | wheelchair_boarding | avg_wait_time | geometry | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | gtfs-data/madrid_gtfs/madrid_metro-par_4_1 | 1 | PLAZA DE CASTILLA | Paseo de la Castellana 189 | 40.46690 | -3.68917 | A | http://www.crtm.es | 0 | est_90_21 | NaN | 0 | 430.357143 | POINT (441575.052 4479808.7) |
1 | gtfs-data/madrid_gtfs/madrid_metro-acc_4_1_1 | 1 | Plaza de Castilla | Paseo de la Castellana 189 | 40.46682 | -3.68918 | NaN | http://www.crtm.es | 2 | est_90_21 | NaN | 0 | NaN | POINT (441574.135 4479799.826) |
2 | gtfs-data/madrid_gtfs/madrid_metro-acc_4_1_1040 | 1 | Ascensor | Plaza de Castilla 9 | 40.46555 | -3.68877 | NaN | http://www.crtm.es | 2 | est_90_21 | NaN | 0 | NaN | POINT (441607.793 4479658.584) |
3 | gtfs-data/madrid_gtfs/madrid_metro-acc_4_1_1043 | 1 | Intercambiador Superficie | Paseo de la Castellana 191 B | 40.46728 | -3.68915 | NaN | http://www.crtm.es | 2 | est_90_21 | NaN | 0 | NaN | POINT (441577.077 4479850.867) |
4 | gtfs-data/madrid_gtfs/madrid_metro-acc_4_1_1044 | 1 | Ascensor | Paseo de la Castellana 189 | 40.46702 | -3.68918 | NaN | http://www.crtm.es | 2 | est_90_21 | NaN | 0 | NaN | POINT (441574.308 4479822.026) |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
1267 | gtfs-data/madrid_gtfs/madrid_metro-est_4_234 | 234 | HOSPITAL SEVERO OCHOA | Avda Orellana 3 | 40.32177 | -3.76797 | B1 | http://www.crtm.es | 1 | NaN | Europe/Madrid | 2 | NaN | POINT (434754.721 4463754.488) |
1268 | gtfs-data/madrid_gtfs/madrid_metro-est_4_235 | 235 | LEGANES CENTRAL | Calle Virgen del Camino 1 | 40.32899 | -3.77154 | B1 | http://www.crtm.es | 1 | NaN | Europe/Madrid | 2 | NaN | POINT (434458.401 4464558.532) |
1269 | gtfs-data/madrid_gtfs/madrid_metro-est_4_236 | 236 | SAN NICASIO | Avda Mar Mediterráneo SN | 40.33616 | -3.77587 | B1 | http://www.crtm.es | 1 | NaN | Europe/Madrid | 2 | NaN | POINT (434097.544 4465357.604) |
1270 | gtfs-data/madrid_gtfs/madrid_metro-par_4_237 | 237 | OPERA | Plaza de Isabel II 9 | 40.41809 | -3.70928 | A | http://www.crtm.es | 0 | est_4_36 | NaN | 0 | 13.214286 | POINT (439826.687 4474404.289) |
1271 | gtfs-data/madrid_gtfs/madrid_metro-par_4_238 | 238 | PRINCIPE PIO | Paseo de la Florida 2 | 40.42099 | -3.72033 | A | http://www.crtm.es | 0 | est_90_18 | NaN | 1 | 13.214286 | POINT (438891.852 4474733.771) |
1272 rows × 14 columns
= layers.compute_accessibilities(
nodes_gdf, prems_gpd
prems_gpd,="division_desc",
landuse_column_label=["retail"],
accessibility_keys=nodes_gdf,
nodes_gdf=network_structure,
network_structure=distances,
distances )
INFO:cityseer.metrics.layers:Computing land-use accessibility for: retail
INFO:cityseer.metrics.layers:Assigning data to network.
INFO:cityseer.data:Assigning 117358 data entries to network nodes (max_dist: 100).
INFO:cityseer.data:Finished assigning data. 198773 assignments added to 24576 nodes.
INFO:cityseer.config:Metrics computed for:
INFO:cityseer.config:Distance: 800m, Beta: 0.005, Walking Time: 10.0 minutes.
INFO:cityseer.config:Distance: 1600m, Beta: 0.0025, Walking Time: 20.0 minutes.
nodes_gdf.columns
Index(['ns_node_idx', 'x', 'y', 'live', 'weight', 'primal_edge',
'primal_edge_node_a', 'primal_edge_node_b', 'primal_edge_idx',
'dual_node', 'cc_retail_800_nw', 'cc_retail_800_wt',
'cc_retail_1600_nw', 'cc_retail_1600_wt', 'cc_retail_nearest_max_1600',
'cc_retail_800_nw_not', 'cc_retail_800_wt_not', 'cc_retail_1600_nw_not',
'cc_retail_1600_wt_not', 'cc_retail_nearest_max_1600_not'],
dtype='object')
"cc_retail_800_wt_diff"] = (
nodes_gdf["cc_retail_800_wt"] - nodes_gdf["cc_retail_800_wt_not"]
nodes_gdf[ )
= plt.subplots(3, 1, figsize=(8, 20), facecolor="#1d1d1d")
fig, axes
nodes_gdf.plot(="cc_retail_800_wt_not",
column="magma",
cmap=True,
legend=axes[0],
ax=450,
vmax
)0].set_title(
axes["Retail Accessibility without Metro Stops",
=8,
fontsize="#ddd",
color
)=axes[0], color="red", markersize=1)
stops_gdf.plot(ax
nodes_gdf.plot(="cc_retail_800_wt",
column="magma",
cmap=True,
legend=axes[1],
ax=450,
vmax
)1].set_title(
axes["Retail Accessibility with Metro Stops",
=8,
fontsize="#ddd",
color
)=axes[1], color="red", markersize=1)
stops_gdf.plot(ax
nodes_gdf.plot(="cc_retail_800_wt_diff",
column="viridis",
cmap=True,
legend=axes[2],
ax
)2].set_title(
axes["Retail Accessibility with difference due to Metro Stops",
=8,
fontsize="#ddd",
color
)
for ax in axes:
"division_desc"] == "retail"].plot(
prems_gpd[prems_gpd[=1,
markersize=None,
edgecolor="white",
color=False,
legend=ax,
ax
)438500, 438500 + 3500)
ax.set_xlim(4472500, 4472500 + 3500)
ax.set_ylim(False)
ax.axis(
plt.tight_layout()