Python 地理数据图的matplotlib和APEC比率

Python 地理数据图的matplotlib和APEC比率,python,matplotlib,aspect-ratio,gis,Python,Matplotlib,Aspect Ratio,Gis,我处理地理信息,并使用 matplotlib。所有输入均为纬度/经度[度]。我转换成 x/y[米]用于我的计算。我将我的结果展示在 纬度/经度。问题是要得到图形的纵横比 右:所有图表都太宽。是否有标准的程序来设置 正确的纵横比,这样我就可以简单地绘制散点图和其他图表 使用lat/lon,结果是否具有正确的形状?银幕上 纸张(png) [稍后添加此部分] 这是我问题的一个赤裸裸的版本。我需要实际的纬度/经度值 围绕轴和精确的形状(方形)。现在它看起来很宽(2x) 在matplotlib中,我通常会

我处理地理信息,并使用 matplotlib。所有输入均为纬度/经度[度]。我转换成 x/y[米]用于我的计算。我将我的结果展示在 纬度/经度。问题是要得到图形的纵横比 右:所有图表都太宽。是否有标准的程序来设置 正确的纵横比,这样我就可以简单地绘制散点图和其他图表
使用lat/lon,结果是否具有正确的形状?银幕上 纸张(png)

[稍后添加此部分] 这是我问题的一个赤裸裸的版本。我需要实际的纬度/经度值 围绕轴和精确的形状(方形)。现在它看起来很宽(2x)


在matplotlib中,我通常会更改图形大小,如下所示:

import matplotlib.pyplot as plt

plt.clf()
fig     = plt.figure()
fig_p   = plt.gcf()
fig_p.set_size_inches(8, 8)    # x, y
但是,这将设置地物外部尺寸,而不是打印区域的尺寸。您可以更改相对于图形大小的打印区域,该图形大小分别以x和y的图形大小总长度的比率给出:

fig.subplots_adjust(left=0.1, right=0.9, bottom=0.1, top=0.9)
只要相对比率保持对称,则绘图的纵横比应相同

例1:

plt.clf()
fig     = plt.figure()
fig_p   = plt.gcf()
fig_p.set_size_inches(5, 5)    # x, y for figure canvas

# Relative distance ratio between origin of the figure and max extend of canvas
fig.subplots_adjust(left=0.2, right=0.8, bottom=0.2, top=0.8)

ax1   = fig.add_subplot(111)
xdata = [rand()*10 for i in xrange(100)]
ydata = [rand()*1  for i in xrange(100)]
ax1.plot(xdata, ydata, '.b', )
ax1.set_xlabel('Very Large X-Label', size=30)
plt.savefig('squareplot.png', dpi=96)

例2:

fig.subplots_adjust(left=0.0, right=1.0, bottom=0.0, top=1.0)
绘图区域完全填充地物大小:


看来我找到了解决办法。 我在这里找到的:


不要试图通过摆弄
fig.set\u size\u inches()
fig.subplot\u adjust()
或更改数据来解决此问题;而是使用墨卡托投影

通过使用数据的平均纬度余弦倒数的纵横比,可以得到快速而肮脏的墨卡托投影。这对于包含在大约1度纬度(约100公里)的数据来说是“非常好的”。(你必须决定,对于你的申请来说,这是“足够好”。如果不是,你真的必须考虑一些严肃的地理投影库……)

例如:

from math import cos, radians
import matplotlib.pyplot as plt
import numpy as np

# Helsinki 60.1708 N, 24.9375 E
# Helsinki (lng, lat)
hels = [24.9375, 60.1708]
# a point 100 km directly north of Helsinki
pt_N = [24.9375, 61.0701]
# a point 100 km east of Helsinki along its parallel
pt_E = [26.7455, 60.1708]

coords = np.array([pt_N, hels, pt_E])

plt.figure()
plt.plot(coords[:,0], coords[:,1])

# either of these will estimate the "central latitude" of your data
# 1) do the plot, then average the limits of the y-axis    
central_latitude = sum(plt.axes().get_ylim())/2.
# 2) actually average the latitudes in your data
central_latitude = np.average(coords, 0)[1]

# calculate the aspect ratio that will approximate a 
# Mercator projection at this central latitude 
mercator_aspect_ratio = 1/cos(radians(central_latitude))

# set the aspect ratio of the axes to that
plt.axes().set_aspect(mercator_aspect_ratio)

plt.show()
我选择赫尔辛基为例,因为在那个纬度,纵横比几乎是2。。。因为两个经度和一个纬度的距离差不多

要真正看到这项工作:a)运行上述操作,b)调整窗口大小。然后注释掉对
set_aspect()
的调用,并执行同样的操作。在第一种情况下,将保持正确的纵横比,在后一种情况下,将得到无意义的拉伸


赫尔辛基以北和以东100公里处的点由移动式脚本的优秀页面计算/确认

我想到了这一点,但我希望它们是设置APEC比率的更精确的方法。现在,我将按照您的建议,保留y尺寸,并设置相对于cos(lat)的x尺寸。非常感谢。在使用这些建议之后,我在原始问题中添加了一个代码示例。您需要多精确?据我所知,“子地块调整”覆盖了其他可能扭曲纵横比的设置,因此应该可以正常工作。从示例代码
w
大约为2,然后您可以:
fig.set\u size\u inches(8,w*8)
。你强迫图形变宽,但你说图形应该是正方形而不是宽的?我不确定我是否理解你的问题。谢谢你的回答。我又试了一次来解释我的问题。
import math
import matplotlib.pyplot as plt
import numpy as np

w=1/math.cos(math.radians(60.0))
plt_area=[0,w,59.5,60.5] #square area

a=np.zeros(shape=(300,300))

fig = plt.figure()
ax = fig.add_subplot(111)

ax.imshow(a)

plt.grid(False)
ax.axis(plt_area)
fig   = plt.gcf()
fig.set_size_inches(8,8)
ax.set_aspect(w)
fig.subplots_adjust(left=0.1, right=0.9, bottom=0.1, top=0.9)

plt.show()
from math import cos, radians
import matplotlib.pyplot as plt
import numpy as np

# Helsinki 60.1708 N, 24.9375 E
# Helsinki (lng, lat)
hels = [24.9375, 60.1708]
# a point 100 km directly north of Helsinki
pt_N = [24.9375, 61.0701]
# a point 100 km east of Helsinki along its parallel
pt_E = [26.7455, 60.1708]

coords = np.array([pt_N, hels, pt_E])

plt.figure()
plt.plot(coords[:,0], coords[:,1])

# either of these will estimate the "central latitude" of your data
# 1) do the plot, then average the limits of the y-axis    
central_latitude = sum(plt.axes().get_ylim())/2.
# 2) actually average the latitudes in your data
central_latitude = np.average(coords, 0)[1]

# calculate the aspect ratio that will approximate a 
# Mercator projection at this central latitude 
mercator_aspect_ratio = 1/cos(radians(central_latitude))

# set the aspect ratio of the axes to that
plt.axes().set_aspect(mercator_aspect_ratio)

plt.show()