【问题标题】:matplotlib and apect ratio of geographical-data plotsmatplotlib 和地理数据图的纵横比
【发布时间】:2016-01-08 21:51:36
【问题描述】:

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

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

import math
import matplotlib.pyplot as plt
import numpy as np
from pylab import *

w=1/math.cos(math.radians(60.0))
plt_area=[0,w,59.5,60.5] #60deg North, adjacent to the prime meridian

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

matshow(a, extent=plt_area)

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

plt.show()

【问题讨论】:

    标签: python matplotlib aspect-ratio gis


    【解决方案1】:

    看来我找到了解决办法。 我在这里找到了它:How can I set the aspect ratio in matplotlib?

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

    【讨论】:

      【解决方案2】:

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

      绘图区域完全填满图形大小:

      【讨论】:

      • 我想到了这一点,但我希望它们会是一种更精确的设置纵横比的方法。现在我会听从你的建议,保持 y 尺寸,并设置相对于 cos(lat) 的 x 尺寸。谢谢!
      • 使用这些建议后,我在原始问题中添加了一个代码示例。
      • 您需要多精确?据我了解,“subplots_adjust”会覆盖其他可能会扭曲纵横比的设置,因此应该可以正常工作。
      • 从您的示例代码中,w 大约是 2,然后您可以:fig.set_size_inches(8,w*8)。您正在强制图形变宽,但您说图形应该是正方形而不是宽?我不确定我是否理解您的问题。
      • 感谢您的回复。我再次尝试解释我的问题。
      【解决方案3】:

      不要试图通过摆弄fig.set_size_inches()fig.subplots_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 公里的点由 Movable Type Scripts 的 EXCELLENT 页面calculating distances between lat/lng points 计算/确认

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-12-29
        • 1970-01-01
        • 2013-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多