如何在Python中设置底图的偏移量?

How to set offset of Basemap in Python?

这是底图的一个示例:

fig = plt.figure(figsize=(10,6))

ax = fig.add_subplot(121)
ax.set_title('Default')

# miller projection
map = Basemap(projection='mill',lon_0=180)
# plot coastlines, draw label meridians and parallels.
map.drawcoastlines()
map.drawparallels(np.arange(-90,90,30),labels=[1,0,0,0])
map.drawmeridians(np.arange(map.lonmin,map.lonmax+30,60),labels=[0,0,0,1])

ax = fig.add_subplot(122)
ax.set_title('Add offset')

# miller projection
map = Basemap(projection='mill',lon_0=180)
# plot coastlines, draw label meridians and parallels.
map.drawcoastlines()
map.drawparallels(np.arange(-90,90,30),labels=[1,0,0,0],xoffset=100,yoffset=100)
map.drawmeridians(np.arange(map.lonmin,map.lonmax+30,60),labels=[0,0,0,1],xoffset=100,yoffset=100)

我想在 xlabel/ylabel 和轴之间添加更多 space。 但是,当 xoffsetyoffset 相加时 space 变小了。

basemap 不再积极开发,但维护仍会持续一段时间。这意味着由于其他软件包的更改而导致的问题仍将得到修复,但不会添加新功能。无论如何,修复部分可能需要一些时间,我猜纬线和经线的 xoffset 功能正在受到影响。但是,查看 basemap 文档,xoffsetyoffset 的功能被描述为

xoffset: label offset from edge of map in x-direction (default is 0.01 times width of map in map projection coordinates).

yoffset: label offset from edge of map in y-direction (default is 0.01 times height of map in map projection coordinates).

这很容易通过操纵 drawparallels()drawmeridians() 产生的 Text 对象来模拟。这些函数的结果存储在 dict 中,其中包含每个绘制的列表的元组 parallel/meridian,其中第二个包含文本标签。 Text 对象有一个 get_position() 和一个 set_position() 方法,结合轴限制和上面的定义,可以用来计算偏移量:

from matplotlib import pyplot as plt
from mpl_toolkits.basemap import Basemap
import numpy as np

fig = plt.figure(figsize=(10,6))

ax = fig.add_subplot(121)
ax.set_title('Default')

# miller projection
map = Basemap(projection='mill',lon_0=180)
# plot coastlines, draw label meridians and parallels.
map.drawcoastlines()
map.drawparallels(np.arange(-90,90,30),labels=[1,0,0,0])
map.drawmeridians(np.arange(map.lonmin,map.lonmax+30,60),labels=[0,0,0,1])

ax = fig.add_subplot(122)
ax.set_title('Add offset')

# miller projection
map = Basemap(projection='mill',lon_0=180)
# plot coastlines, draw label meridians and parallels.
map.drawcoastlines()

##getting axes dimensions
x0,x1 = ax.get_xlim()
w = x1-x0
y0,y1 = ax.get_ylim()
h = y1-y0

xoffset = 0.05
yoffset = 0.05

result = map.drawparallels(np.arange(-90,90,30),labels=[1,0,0,0])
##
for key, (lines,texts) in result.items():
    for text in texts:
        x,y = text.get_position()
        text.set_position((x0-xoffset*w,y))


result = map.drawmeridians(np.arange(map.lonmin,map.lonmax+30,60),labels=[0,0,0,1])
for key, (lines,texts) in result.items():
    for text in texts:
        x,y = text.get_position()
        text.set_position((x,y0-yoffset*h))



plt.show()

结果图如下所示:

我认为您使用的单位不正确。 @Thomas Kühn 引用底图文档:

xoffset: label offset from edge of map in x-direction (default is 0.01 times width of map in map projection coordinates).

yoffset: label offset from edge of map in y-direction (default is 0.01 times height of map in map projection coordinates).

请注意,它默认为 地图投影坐标 中测量的域跨度的 1%。

如果你检查你使用的mill projection在y轴上的跨度,长度有8位,所以难怪yoffset=100没有视觉偏移。

所以更简单的方法是使用实​​际域跨度修改偏移量,例如:

map.drawmeridians(np.arange(map.lonmin,map.lonmax+30,60),labels=[0,0,0,1],
        yoffset=0.01*abs(map.ymax-map.ymin))

这给出了与默认值相同的偏移量,即域跨度的 1%(参见下图 (b))。将 0.01 更改为 0.03 将是它的 3 倍(图 (c))。

如果您改为使用 cyl 投影,它使用 latitude/longitude 的度数作为单位,偏移量也以度数为单位,那么 yoffset=100 将是一个疯狂的偏移量。图(f)中用了一个yoffset=30,注意和60S到90S的距离是一样的。

生成图形的脚本:

import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import numpy as np
fig = plt.figure(figsize=(12,6))

def drawMap(proj):
    map = Basemap(projection=proj,lon_0=180)
    map.drawcoastlines()
    return map

# miller projection
ax = fig.add_subplot(231)
ax.set_title('(a) Mill, Default')
map=drawMap('mill')
map.drawparallels(np.arange(-90,90,30),labels=[1,0,0,0])
map.drawmeridians(np.arange(map.lonmin,map.lonmax+30,60),labels=[0,0,0,1])

ax = fig.add_subplot(232)
ax.set_title('(b) Mill, add same offset as default')
map=drawMap('mill')
map.drawparallels(np.arange(-90,90,30),labels=[1,0,0,0],
        xoffset=0.01*abs(map.xmax-map.xmin))
map.drawmeridians(np.arange(map.lonmin,map.lonmax+30,60),labels=[0,0,0,1],
        yoffset=0.01*abs(map.ymax-map.ymin))

ax = fig.add_subplot(233)
ax.set_title('(c) Mill, add 3x offset as default')
map=drawMap('mill')
map.drawparallels(np.arange(-90,90,30),labels=[1,0,0,0],
        xoffset=0.03*abs(map.xmax-map.xmin))
map.drawmeridians(np.arange(map.lonmin,map.lonmax+30,60),labels=[0,0,0,1],
        yoffset=0.03*abs(map.ymax-map.ymin))

ax = fig.add_subplot(234)
ax.set_title('(d) Cyl, Default')
map=drawMap('cyl')
map.drawparallels(np.arange(-90,90,30),labels=[1,0,0,0])
map.drawmeridians(np.arange(map.lonmin,map.lonmax+30,60),labels=[0,0,0,1])

ax = fig.add_subplot(235)
ax.set_title('(e) Cyl, add same offset as default')
map=drawMap('cyl')
map.drawparallels(np.arange(-90,90,30),labels=[1,0,0,0],
        xoffset=0.01*abs(map.xmax-map.xmin))
map.drawmeridians(np.arange(map.lonmin,map.lonmax+30,60),labels=[0,0,0,1],
        yoffset=0.01*abs(map.ymax-map.ymin))

ax = fig.add_subplot(236)
ax.set_title('(f) Cyl, add 30 degree offset')
map=drawMap('cyl')
map.drawparallels(np.arange(-90,90,30),labels=[1,0,0,0],
        xoffset=0.03*abs(map.xmax-map.xmin))
map.drawmeridians(np.arange(map.lonmin,map.lonmax+30,60),labels=[0,0,0,1],
        yoffset=30)

fig.subplots_adjust(hspace=0.01)
fig.show()