首页 > 解决方案 > 用 Geopandas 绘制以日本为中心的世界地图

问题描述

在阅读我的问题之前,我的英语水平很差,所以请给我反馈或用简单的话给我建议。谢谢你。

我想做的事:

我想用python 3.x上的geopandas库绘制一个以日本为中心的世界地图。

我的环境:

我的代码:

import geopandas

world = geopandas.read_file(geopandas.datasets.get_path("naturalearth_lowres"))
world.boundary.plot(figsize=(15,8))

获得的图像

世界形象

问题:

获得的世界地图的中心在非洲周围。我想绘制以日本为中心的图像。我阅读了官方文档:Mapping and Plotting Tools,但我找不到如何实现它。请告诉我建议!

标签: python-3.xwindowsgeopandas

解决方案


我发现使用geopandas(+pyproj作为它的依赖项)来获得移位的地图太困难了。在我下面的代码中,geopandas用于提供世界的地理数据框以进行操作和绘图。Cartopy用于提供geoaxis适当的地理空间参考。并shapely用于进行各种操作以转换几何图形以绘制重新居中的世界图以满足问题中的要求。

import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from shapely.geometry import LineString, MultiPolygon, Polygon
from shapely.ops import split
from shapely.affinity import translate

from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
import geopandas

def shift_map(world_gdf, shift, ax):
    # world_gdf: world geodataframe to shift
    # shift: longitude shift
    # ax: geoaxis to plot the map
    shift -= 180
    moved_map = []
    splitted_map = []
    border = LineString([(shift,90),(shift,-90)])
    for row in world_gdf["geometry"]:
        splitted_map.append(split(row, border))
    for element in splitted_map:
        items = list(element)
        for item in items:
            minx, miny, maxx, maxy = item.bounds
            if minx >= shift:
                moved_map.append(translate(item, xoff=-180-shift))
            else:
                moved_map.append(translate(item, xoff=180-shift))

    gdf = geopandas.GeoDataFrame({"geometry": moved_map})
    gdf.boundary.plot(ax=ax, linewidth=1, color='gray')
    # can also use: gdf.plot() to plot the geometries as polygons


# define CRS's 
crs0 = ccrs.PlateCarree(central_longitude=0)         # standard CRS
lon_0 = 138                                          # Japan at center
# crsJapan = ccrs.PlateCarree(central_longitude=lon_0) # japan's centered; not in-use
# a special CRS for use with ax1.gridlines() to get correct longitude's labels plot
crsGridLines = ccrs.PlateCarree(central_longitude=-lon_0)

# create figure, axis
# use cartopy ccrs to get some niceties
fig, ax1 = plt.subplots(figsize=(8, 4.5), subplot_kw={"projection": crs0})

# load world geodataframe
world = geopandas.read_file(geopandas.datasets.get_path("naturalearth_lowres"))

# Plot the shifted map
shift_map(world, lon_0, ax1)

# Plot graticule/grid; only work with geoaxis
gl = ax1.gridlines(crs=crsGridLines, draw_labels=True, linewidth=1, color='gray', linestyle='--')
gl.xformatter = LONGITUDE_FORMATTER
gl.yformatter = LATITUDE_FORMATTER
gl.xlabel_style = {'size': 10, 'color': 'black'}
gl.ylabel_style = {'size': 10, 'color': 'black'}

plt.show()

以日本为中心的地图


推荐阅读