基于特定规则对Shapely多边形列表进行分组的技术咨询
Got it, let's work through grouping your polys list of Shapely Polygons. Since you mentioned a "specific rule" but didn't dive into details, I'll walk through three common grouping scenarios you might be targeting, with ready-to-use code snippets tailored to your setup.
1. Group by Spatial Intersection/Touching
If you want to group polygons that overlap, intersect, or touch each other (i.e., connected spatial components), here's a solid graph-based connected components approach:
from itertools import compress from shapely.geometry import Polygon import networkx as nx # Install first via `pip install networkx` # Your existing polygon list polys = [<shapely.geometry.polygon.Polygon object at 0x000002D634217668>, <shapely.geometry.polygon.Polygon object at 0x000002D634217780>, <shapely.geometry.polygon.Polygon object at 0x000002D6341F9080>, <shapely.geometry.polygon.Polygon object at 0x000002D634217FD0>, <shapely.geometry.polygon.Polygon object at 0x000002D634217F60>] # Build a graph where nodes = polygon indices, edges link intersecting polygons G = nx.Graph() G.add_nodes_from(range(len(polys))) for i in range(len(polys)): for j in range(i+1, len(polys)): # Swap to .touches() if you only want polygons that touch (no overlap) if polys[i].intersects(polys[j]): G.add_edge(i, j) # Extract connected components (each component is a group of polygon indices) index_groups = list(nx.connected_components(G)) # Convert index groups back to actual polygon groups polygon_groups = [[polys[idx] for idx in group] for group in index_groups] # Check results for idx, group in enumerate(polygon_groups): print(f"Group {idx+1}: {len(group)} connected polygons")
2. Group by Custom Attributes
If your polygons have associated labels, area ranges, or other attributes, itertools.groupby is perfect. Let's assume you have a matching list of attributes for your polys:
from itertools import compress, groupby from shapely.geometry import Polygon # Your polygon list polys = [<shapely.geometry.polygon.Polygon object at 0x000002D634217668>, <shapely.geometry.polygon.Polygon object at 0x000002D634217780>, <shapely.geometry.polygon.Polygon object at 0x000002D6341F9080>, <shapely.geometry.polygon.Polygon object at 0x000002D634217FD0>, <shapely.geometry.polygon.Polygon object at 0x000002D634217F60>] # Example attribute list (matches order of polys) poly_categories = ["residential", "commercial", "residential", "industrial", "commercial"] # Sort pairs first (required for groupby to work correctly) sorted_pairs = sorted(zip(polys, poly_categories), key=lambda x: x[1]) # Group polygons by their category polygon_groups = {} for category, group in groupby(sorted_pairs, key=lambda x: x[1]): polygon_groups[category] = [poly for poly, _ in group] # Check results for cat, group in polygon_groups.items(): print(f"{cat.capitalize()} group: {len(group)} polygons")
For derived attributes like area ranges, replace the static category list with computed values:
# Group by area size (small/medium/large) def get_area_bucket(poly): area = poly.area if area < 100: return "small" elif area < 500: return "medium" else: return "large" sorted_pairs = sorted(zip(polys, [get_area_bucket(p) for p in polys]), key=lambda x: x[1])
3. Group by Spatial Clustering (Distance-Based)
If you want to group polygons that are geographically close, use DBSCAN clustering on their centroid coordinates:
from itertools import compress from shapely.geometry import Polygon from sklearn.cluster import DBSCAN # Install first via `pip install scikit-learn` import numpy as np # Your polygon list polys = [<shapely.geometry.polygon.Polygon object at 0x000002D634217668>, <shapely.geometry.polygon.Polygon object at 0x000002D634217780>, <shapely.geometry.polygon.Polygon object at 0x000002D6341F9080>, <shapely.geometry.polygon.Polygon object at 0x000002D634217FD0>, <shapely.geometry.polygon.Polygon object at 0x000002D634217F60>] # Extract centroid coordinates for each polygon centroids = np.array([[poly.centroid.x, poly.centroid.y] for poly in polys]) # Run DBSCAN (adjust eps and min_samples to fit your spatial scale) dbscan = DBSCAN(eps=100, min_samples=1) # eps = max distance between clustered points cluster_labels = dbscan.fit_predict(centroids) # Group polygons by their cluster label polygon_groups = {} for label in set(cluster_labels): # Filter polygons matching the current cluster label group = list(compress(polys, cluster_labels == label)) polygon_groups[label] = group # Check results for label, group in polygon_groups.items(): print(f"Cluster {label}: {len(group)} nearby polygons")
Just tweak the logic in whichever scenario fits your "specific rule"—if you had a different grouping criteria in mind, adjust the condition checks or clustering parameters accordingly!
内容的提问来源于stack exchange,提问作者Roman

