子图对应于底图 Python 的直方图
Subplot a histogram corresponding to the plot of a Basemap Python
这是我必须在底图上绘制地理定位数据的代码。我想在我的底图左侧添加一个直方图,以显示与每个纬度相关的密度。
data = np.zeros((5000,3))
data[:,0]=np.random.uniform(low=-180,high=180,size=(5000,))
data[:,1]=np.random.uniform(low=-60,high=90,size=(5000,))
data[:,2] =np.random.uniform(low=0,high=100000,size=(5000,))
fig = plt.figure(facecolor='w')
grid = plt.GridSpec(4, 4, hspace=0.2, wspace=0.2)
main_ax = fig.add_subplot(grid[:-1, 1:])
m = Basemap(projection = 'cyl', llcrnrlat = -60., urcrnrlat = 90., llcrnrlon = -180., urcrnrlon = 180., resolution ='l')
x, y =m(data[:,0], data[:,1])
m.scatter(x, y, marker='.', s = 0.02, c = data_lac[:,2], cmap = 'hot_r', edgecolor = 'none')
m.fillcontinents(color='grey', lake_color=None, ax=None, alpha=0.1)
parallels=np.arange(-60.,90.,10)
m.drawparallels(parallels, labels =[True, False, False, True], linewidth=0.)
m.drawmeridians(np.arange(-180.,180.,20),labels =[True, False, False, True], linewidth=0. )
m.colorbar()
y_hist = fig.add_subplot(grid[:-1, 0], xticklabels=[], sharey=main_ax)
# histogram on the attached axes
y_hist.hist(data[:,1], 150, histtype='stepfilled', orientation='horizontal', color='blue',alpha=0.2)
y_hist.invert_xaxis()
plt.tight_layout()
plt.show()
我的直方图大小不适合地图大小和纬度(如果我只想从 -60° 到 90°)。此外,y 轴不在底图和直方图之间共享。
我也尝试了 GridSpec 格式,但结果是一样的。
虽然我在评论中链接的答案提供了问题的原理解决方案,但当图形的纵横比为'too small'时,可能会出现问题。在这种情况下,即使 yticks 和 ylims 同步了,底图和直方图的高度却不同步,因为两个子图的纵横比不同。解决这个问题的最简单方法是使用轴分隔符而不是通常的 add_subplot()
方法,就像在 .
的最后一个示例中所做的那样
与我之前的 suggested solution to share the yticks between the two plots, one can actually get pretty neat results. For best results, I would recommend to not use basemaps colorbar
function, but instead directly use fig.colorbar
with a dedicated axes for the color bar. Also, it looks (in my opinion) best if you show the ytick labels only left of the histogram and hide them next to the basemap (solution from here) 有关。如果不需要,您可以使用 divider.append_axes()
.
中的 pad
关键字调整直方图和底图之间的距离
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.basemap import Basemap
from mpl_toolkits.axes_grid1 import make_axes_locatable
data = np.zeros((5000,3))
data[:,0] = np.random.normal(loc=20, scale = 30, size=(5000,))
data[:,1] = np.random.normal(loc=50, scale=10, size=(5000,))
data[:,2] =np.random.uniform(low=0,high=100000,size=(5000,))
##create a figure with just the main axes:
fig, main_ax = plt.subplots()
m = Basemap(
projection = 'cyl',
llcrnrlat = -60., urcrnrlat = 90.,
llcrnrlon = -180., urcrnrlon = 180.,
resolution ='l',
ax=main_ax,
)
x, y =m(data[:,0], data[:,1])
cls = m.scatter(
x, y,
marker='.', s = 1, c = data[:,2],
cmap = 'hot_r', edgecolor = 'none'
)
m.fillcontinents(color='grey', lake_color=None, ax=None, alpha=0.1)
lats=np.arange(-60.,90.,10)
lons=np.arange(-180.,180.,60)
##parallels without labels
m.drawparallels(lats, labels =[False, False, False, False], linewidth=0.1)
m.drawmeridians(lons,labels =[False, False, False, True], linewidth=0.1 )
##generating the other axes instances:
##if you want labels at the left side of the map,
##adjust pad to make them visible
divider = make_axes_locatable(main_ax)
y_hist = divider.append_axes('left', size='20%', pad='5%', sharey=main_ax)
cax = divider.append_axes('right',size=0.1,pad=0.1)
##use fig.colorbar instead of m.colorbar
fig.colorbar(cls, cax = cax)
## histogram on the attached axes
y_hist.hist(data[:,1], 150, histtype='stepfilled', orientation='horizontal', color='blue',alpha=0.2)
y_hist.invert_xaxis()
##the y-ticklabels:
_,yticks_data = m(0*lats,lats)
y_hist.set_yticks(yticks_data)
y_hist.set_yticklabels(['{: >3}$^\circ${}'.format(
abs(int(y)), 'N' if y>0 else 'S' if y<0 else ' '
) for y in lats])
##turning off yticks at basemap
main_ax.yaxis.set_ticks_position('none')
plt.setp(main_ax.get_yticklabels(), visible=False)
plt.tight_layout()
plt.show()
最终结果具有真正同步的子图高度和 yticks(也在调整图形大小时)并且看起来像这样:
这是我必须在底图上绘制地理定位数据的代码。我想在我的底图左侧添加一个直方图,以显示与每个纬度相关的密度。
data = np.zeros((5000,3))
data[:,0]=np.random.uniform(low=-180,high=180,size=(5000,))
data[:,1]=np.random.uniform(low=-60,high=90,size=(5000,))
data[:,2] =np.random.uniform(low=0,high=100000,size=(5000,))
fig = plt.figure(facecolor='w')
grid = plt.GridSpec(4, 4, hspace=0.2, wspace=0.2)
main_ax = fig.add_subplot(grid[:-1, 1:])
m = Basemap(projection = 'cyl', llcrnrlat = -60., urcrnrlat = 90., llcrnrlon = -180., urcrnrlon = 180., resolution ='l')
x, y =m(data[:,0], data[:,1])
m.scatter(x, y, marker='.', s = 0.02, c = data_lac[:,2], cmap = 'hot_r', edgecolor = 'none')
m.fillcontinents(color='grey', lake_color=None, ax=None, alpha=0.1)
parallels=np.arange(-60.,90.,10)
m.drawparallels(parallels, labels =[True, False, False, True], linewidth=0.)
m.drawmeridians(np.arange(-180.,180.,20),labels =[True, False, False, True], linewidth=0. )
m.colorbar()
y_hist = fig.add_subplot(grid[:-1, 0], xticklabels=[], sharey=main_ax)
# histogram on the attached axes
y_hist.hist(data[:,1], 150, histtype='stepfilled', orientation='horizontal', color='blue',alpha=0.2)
y_hist.invert_xaxis()
plt.tight_layout()
plt.show()
我的直方图大小不适合地图大小和纬度(如果我只想从 -60° 到 90°)。此外,y 轴不在底图和直方图之间共享。 我也尝试了 GridSpec 格式,但结果是一样的。
虽然我在评论中链接的答案提供了问题的原理解决方案,但当图形的纵横比为'too small'时,可能会出现问题。在这种情况下,即使 yticks 和 ylims 同步了,底图和直方图的高度却不同步,因为两个子图的纵横比不同。解决这个问题的最简单方法是使用轴分隔符而不是通常的 add_subplot()
方法,就像在
与我之前的 suggested solution to share the yticks between the two plots, one can actually get pretty neat results. For best results, I would recommend to not use basemaps colorbar
function, but instead directly use fig.colorbar
with a dedicated axes for the color bar. Also, it looks (in my opinion) best if you show the ytick labels only left of the histogram and hide them next to the basemap (solution from here) 有关。如果不需要,您可以使用 divider.append_axes()
.
pad
关键字调整直方图和底图之间的距离
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.basemap import Basemap
from mpl_toolkits.axes_grid1 import make_axes_locatable
data = np.zeros((5000,3))
data[:,0] = np.random.normal(loc=20, scale = 30, size=(5000,))
data[:,1] = np.random.normal(loc=50, scale=10, size=(5000,))
data[:,2] =np.random.uniform(low=0,high=100000,size=(5000,))
##create a figure with just the main axes:
fig, main_ax = plt.subplots()
m = Basemap(
projection = 'cyl',
llcrnrlat = -60., urcrnrlat = 90.,
llcrnrlon = -180., urcrnrlon = 180.,
resolution ='l',
ax=main_ax,
)
x, y =m(data[:,0], data[:,1])
cls = m.scatter(
x, y,
marker='.', s = 1, c = data[:,2],
cmap = 'hot_r', edgecolor = 'none'
)
m.fillcontinents(color='grey', lake_color=None, ax=None, alpha=0.1)
lats=np.arange(-60.,90.,10)
lons=np.arange(-180.,180.,60)
##parallels without labels
m.drawparallels(lats, labels =[False, False, False, False], linewidth=0.1)
m.drawmeridians(lons,labels =[False, False, False, True], linewidth=0.1 )
##generating the other axes instances:
##if you want labels at the left side of the map,
##adjust pad to make them visible
divider = make_axes_locatable(main_ax)
y_hist = divider.append_axes('left', size='20%', pad='5%', sharey=main_ax)
cax = divider.append_axes('right',size=0.1,pad=0.1)
##use fig.colorbar instead of m.colorbar
fig.colorbar(cls, cax = cax)
## histogram on the attached axes
y_hist.hist(data[:,1], 150, histtype='stepfilled', orientation='horizontal', color='blue',alpha=0.2)
y_hist.invert_xaxis()
##the y-ticklabels:
_,yticks_data = m(0*lats,lats)
y_hist.set_yticks(yticks_data)
y_hist.set_yticklabels(['{: >3}$^\circ${}'.format(
abs(int(y)), 'N' if y>0 else 'S' if y<0 else ' '
) for y in lats])
##turning off yticks at basemap
main_ax.yaxis.set_ticks_position('none')
plt.setp(main_ax.get_yticklabels(), visible=False)
plt.tight_layout()
plt.show()
最终结果具有真正同步的子图高度和 yticks(也在调整图形大小时)并且看起来像这样: