Reputation: 107
Before reading my question, my english skill is poor, so please send me feedback or advise in easy words. Thank you.
I want to draw an worldmap whose center is Japan with geopandas library on python 3.x.
import geopandas
world = geopandas.read_file(geopandas.datasets.get_path("naturalearth_lowres"))
world.boundary.plot(figsize=(15,8))
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
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()
Upvotes: 1