kazutaka
kazutaka

Reputation: 107

Drawing Worldmap Whose Center Is Japan With Geopandas

Before reading my question, my english skill is poor, so please send me feedback or advise in easy words. Thank you.

What I wand to do:

I want to draw an worldmap whose center is Japan with geopandas library on python 3.x.

My Environment:

My Code:

import geopandas

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

The Obtained Image

world image

Question:

The center of an obtained worldmap drawing is arouond Africa. I want to draw the image whose center is Japan. I read an official document: Mapping and Plotting Tools, but I can not find how to realize it. Please tell me advices !!

Upvotes: 0

Views: 452

Answers (1)

swatchai
swatchai

Reputation: 18782

I found working with geopandas (+ pyproj as its dependency) to get the shifted map is too difficult. In my code below, geopandas is used to provide the geodataframe of the world to manipulate and plot. Cartopy is used to provide the geoaxis for proper geospatial referencing. And shapely is used to do all sorts of manipulation to transform geometries for plotting re-centered world plot to meet the requirements in the question.

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()

japan-centered-map

Upvotes: 1

Related Questions