2

请原谅我,因为这是我第一次参加 Python 的“项目”。

快速概述:我正在尝试通过迭代包含活动细分阶段边界的 GeoJSON 文件的 GeoPandas 数据框来生成地图(MatPlotLib 图),以显示每个细分阶段中各个批次的构建进度。我们通常在 GIS 中手动执行此操作,但我想我会尝试自动化部分或全部过程。我也试图在不使用 ESRI 的 python 功能的情况下做到这一点,并且更愿意保持这种方式以供将来使用,因为 ESRI 可以移动很多。

我能够遍历地理数据框并生成一个缩放到细分阶段边界范围的地图(图),但是,它将背景航空影像底图裁剪到我一直在细分阶段的最小绑定框用于设置图形的“缩放”。

我打算生产的示例。这是在 ArcGIS Pro 中制作的:

我打算生产的示例。 这是在 ArcGIS Pro 中制作的。

我能用 Python 做什么: 我能用 Python 做什么。

我无法将底图设置为填充标准横向字母页面的恒定大小,同时仍正确放大到细分阶段的范围。我的输出 jpeg 大小正确,但航空影像底图被连续裁剪到细分相位边界的范围,在图形周围留下大边界。

import geopandas as gpd # extension to Pandas to work with geodata
import urllib.request, json # download from the web
import os.path # work with the local file system
from shapely.geometry import Point # basic functions to work with vector geometries
import matplotlib as mpl # plotting
from matplotlib import pyplot as plt # some matplotlib convenience functions
import contextily as ctx # simple free basemaps
import csv # read .csv files
import time # time tracking for processes
from matplotlib.patches import Patch # build legend items
from matplotlib.lines import Line2D # build legend items
from matplotlib import figure # change size of figures

start_time = time.time() # Keep track of execution time

# Build Legend Elements
legend_elements = [Patch(facecolor='green', edgecolor='r', alpha=0.5, 
                         label='Completed Lots'),
                   Patch(facecolor='red', edgecolor='black', alpha=0.5, 
                         label='Lots Under Construction'),
                   Patch(facecolor='none', edgecolor='r',
                         label='Subdivision Boundary')]

for index, row in phases.iterrows():
    name = row['NAME']
    print(name)
    lots_complete_select = lots_complete[(lots_complete['SUBDIVISION'] == row['NAME'])]
    print('Completed Lots: ' + str(len(lots_complete_select)))
    lots_uc_select = lots_uc[(lots_uc['SUBDIVISION'] == row['NAME'])]
    print('Lots Under Construction: ' + str(len(lots_uc_select)))
    phase_select = phases[(phases['NAME'] == row['NAME'])]
    lots_select = lots[(lots['SUBDIVISION'] == row['NAME'])]
    print('Lots in subdivision: ' + str(len(lots_select)))
    
    minx, miny, maxx, maxy = (lots_select).total_bounds # Set zoom to lots for area of interest
    
    map_time = time.time()
    print('Building map...')
    fig, ax = plt.subplots() # Create a figure with multiple plots within it
    ax.set_aspect('equal')
    ax.axis('off') # Turn off axes

    ax.set_xlim(minx, maxx) # Apply x zoom level
    ax.set_ylim(miny, maxy) # Apply y zoom level
    
    streets.plot(ax=ax, linewidth=1.2, color='black') # Plot Streets
    
    lots_complete_select.plot(ax=ax, linewidth=0.5, color='green', edgecolor='red', alpha=0.5) # Plot completed lots
    
    lots_uc_select.plot(ax=ax, linewidth=0.5, color='red', edgecolor='black', alpha=0.5) # Plot U.C. lots
    
    lots.plot(ax=ax, linewidth=0.7, color='none', edgecolor='black') # Plot lot lines
    
    phase_select.plot(ax=ax, linewidth=4, color='none', edgecolor='black') # Plot Active Subdivision Phases
    phase_select.plot(ax=ax, linewidth=2, color='none', edgecolor='red') # Plot Active Subdivision Phases
    phase_select.plot(ax=ax, linewidth=1, color='none', edgecolor='white') # Plot Active Subdivision Phases
    
    ctx.add_basemap(ax, crs=streets.crs.to_string(), source=ctx.providers.Esri.WorldImagery, 
                    attribution='City of Pflugerville GIS Services') # Change basemap
        
    ax.set_title((name + ' Residential Construction'), fontsize=10, fontweight ="bold") # Set title
    
    ax.legend(handles=legend_elements, prop={'size': 6}, title='Legend', framealpha=1, fancybox=False, 
              edgecolor='black', loc='upper left') # Add legend
                
    plt.savefig(save_path + name + '.jpg', edgecolor='black', orientation='landscape', papertype='letter', 
                dpi=300) # Save map
        
    print('Map saved.')
    print('Done building map.')
    print("--- %s Seconds ---" % (time.time() - map_time) + '\n')

print('Done configuring maps.')
print("--- %s Minutes ---" % ((time.time() - start_time)/60))

我尝试figsize=(11, 8.5)在代码周围的各个地方使用,但没有效果。

任何投入将不胜感激。请让我知道是否有任何需要更改/澄清的地方。

此外,如果有人熟悉在 Python 中标记线特征(例如街道),是否有一种方法可以在 Python 中以类似于第一张图像中看到的方式标记街道?

4

1 回答 1

0

如果你想有一个固定的区域,比如说,将边界框扩展 10m,你必须设置xlimylim扩展。您正在将两者都明确指定到边界框。

margin = 10
ax.set_xlim(minx - margin, maxx + margin)
ax.set_ylim(miny - margin, maxy + margin)

此外,要删除绘图周围的白色边界,您可以在保存中设置bbox_inches为。tight

plt.savefig(save_path + name + '.jpg', edgecolor='black', orientation='landscape', papertype='letter', 
                dpi=300, bbox_inches='tight') # Save map
于 2020-10-19T17:59:02.540 回答