You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用Matplotlib绘制坐标致底图变形的原因及解决方法问询

地图标记点绘制时底图变形的根源与解决方法

我来帮你拆解这个问题——你遇到的地图变形,核心原因是坐标系的选择和使用不规范,具体来说:

变形的根源

  1. 地理坐标系直接绘图的固有缺陷
    你给底图多边形设置的epsg:4326是地理坐标系(经纬度坐标系),它是基于地球球面的坐标系统。但Matplotlib绘制地图时,会把经纬度当作平面直角坐标来渲染——这就会在高纬度区域(比如你数据里的60°N附近)产生严重的横向拉伸:因为经度的实际地表距离在高纬度会比赤道短很多,但平面绘图时每个经度间隔的像素宽度是一致的,直接导致地图形状扭曲。

  2. 商铺GeoDataFrame缺少CRS定义
    你创建商铺的GeoDataFrame时,没有指定crs='epsg:4326',虽然点是从经纬度生成的,但GeoPandas不知道它的坐标系统,后续转换投影时会出错,不过这不是变形的直接原因,但也是需要修正的规范问题。


如何避免变形:转换为投影坐标系

要解决这个问题,关键是把地理坐标系转换为投影坐标系——这类坐标系是专门为平面绘图设计的,能保持区域内的空间比例、距离和形状正确。对于小范围区域,UTM(通用横轴墨卡托)投影是最优选择。

步骤1:修正商铺GeoDataFrame的CRS设置

创建shops时,一定要明确指定坐标系统:

shops = gpd.GeoDataFrame(coordinates, geometry=gpd.points_from_xy(df.longitude, df.latitude), crs='epsg:4326')

步骤2:统一转换为合适的投影坐标系

你的数据位于60°N、24-25°E,对应UTM 35N分区,EPSG代码是32635。把底图和商铺数据都转换到这个投影:

# 转换投影
polygon_proj = polygon.to_crs(epsg=32635)
shops_proj = shops.to_crs(epsg=32635)

如果你不确定自己的区域对应哪个UTM分区,可以用GeoPandas的自动估算方法:

utm_crs = polygon.estimate_utm_crs()
polygon_proj = polygon.to_crs(utm_crs)
shops_proj = shops.to_crs(utm_crs)

步骤3:用投影后的数据绘图

最后用转换后的GeoDataFrame绘图,就能得到无变形的地图了。


完整修正后的代码

import pandas as pd
import geopandas as gpd
import matplotlib.pyplot as plt
from shapely.geometry import Polygon

# 创建简化多边形(地理坐标系)
latitude = [60.41125, 59.99236, 59.99236]
longitude = [24.66917, 24.66917, 25.36972]
geometry = Polygon(zip(longitude, latitude))
polygon = gpd.GeoDataFrame(index=[0], crs='epsg:4326', geometry=[geometry])

# 商铺坐标数据
coordinates = {"latitude": ["60.193141", "60.292777", "60.175053", "60.163187", "60.245272", "60.154392", "60.182906"], 
               "longitude": ["24.934214", "24.969730", "24.831068", "24.739044", "24.860983", "24.884773", "24.959175"]}
df = pd.DataFrame(coordinates)

# 创建商铺GeoDataFrame并指定地理坐标系
shops = gpd.GeoDataFrame(coordinates, geometry=gpd.points_from_xy(df.longitude, df.latitude), crs='epsg:4326')

# 自动估算并转换为合适的UTM投影
utm_crs = polygon.estimate_utm_crs()
polygon_proj = polygon.to_crs(utm_crs)
shops_proj = shops.to_crs(utm_crs)

# 绘制无变形的地图
ax = polygon_proj.plot(color="#3791CB")
shops_proj.plot(ax=ax, color="red", markersize=20, zorder=2)

plt.grid(linestyle=":", color='grey')
plt.show()

内容的提问来源于stack exchange,提问作者user14074311

火山引擎 最新活动