我有一张英国的地图和121个位置,每个位置都有3个值。我想在121个位置的每一个上绘制三个值的小条形图。
当前,值被绘制为markersize
属性,如下所示:
Trypophobic_Plot
使用以下代码制作:(大大简化)
fig, ax = plt.subplots()
ax = Basemap(llcrnrlat= 46.351611,
llcrnrlon= -11.543011,
urcrnrlat= 60.417133,
urcrnrlon= 6.2743413,
resolution='i', projection='tmerc', lon_0=-2, lat_0=49)
#Draw Coastlines, colours etc.
(removed because not important to this example)
################################################
# Plot Network edge map
(not important to this example)
################################################
# Plot SYNOP Station Points
lats = [59.5329945921, 58.9499976059, 57.3669959942...]
lons = [-1.63299557989, -2.90000295719, -7.40000487601...]
for method in range (0,3):
for i in range(0, len(lons)):
x,y = ax(lons[i], lats[i])
ax.plot(x, y, 'o', color=(1,1,1,0), \
markersize= ..., \
markeredgecolor=..., \
markeredgewidth=7)
################################################
# Other plot features
plt.text(10000, 10000,'Max: = ' ... + \
'\nMin: = ' ..., \
fontsize=32, zorder=75.)
plt.title('site_scores' , fontsize=30)
plt.show()
但是,我想要一个条形图。我要解决的方法是为121个位置中的每个位置绘制一个子图。这可能效率不高,所以如果您认为有更好的方法,请提出另一种方法。
我尝试过的事情:
我开始研究在纬度/经度和图形的实轴之间进行转换,这有点令人困惑。有display
,axes
,data
和Figure
。我无法在此处将转换操作数:https://matplotlib.org/users/transforms_tutorial.html应用于ax
坐标。您可以在上面的代码中看到如何制作圆,但是我不知道将其切换到哪个坐标系。
然后我以为我会尝试像平常一样添加一个轴,然后查看它的出现位置。像这样:
ax3 = fig.add_axes([0.5,0.5, 0.2, 0.2])
但这会导致有关绘图大小的错误:
ValueError: Image size of 5690009x6001228 pixels is too large. It must be less than 2^16 in each direction.
这就是我目前要处理的内容。我想用一点条形图来画出这些圆圈的大小。
答案 0 :(得分:0)
下面的代码使用inset_axes
在地图上的每个位置绘制每个条形图。如果您将figure
的大小设置得较大,则条形图应更整洁。
from mpl_toolkits.basemap import Basemap
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.patches as mpatches
# prep values for map extents and more
llcrnrlat = 46.351611
llcrnrlon = -11.543011
urcrnrlat = 60.417133
urcrnrlon = 6.2743413
mid_lon = (urcrnrlon+llcrnrlon)/2.0
hr_lon = (urcrnrlon-llcrnrlon)/2.0
mid_lat = (urcrnrlat+llcrnrlat)/2.0
hr_lat = (urcrnrlat-llcrnrlat)/2.0
# function to create inset axes and plot bar chart on it
# this is good for 3 items bar chart
def build_bar(mapx, mapy, ax, width, xvals=['a','b','c'], yvals=[1,4,2], fcolors=['r','y','b']):
ax_h = inset_axes(ax, width=width, \
height=width, \
loc=3, \
bbox_to_anchor=(mapx, mapy), \
bbox_transform=ax.transData, \
borderpad=0, \
axes_kwargs={'alpha': 0.35, 'visible': True})
for x,y,c in zip(xvals, yvals, fcolors):
ax_h.bar(x, y, label=str(x), fc=c)
#ax.xticks(range(len(xvals)), xvals, fontsize=10, rotation=30)
ax_h.axis('off')
return ax_h
fig, ax = plt.subplots(figsize=(10, 9)) # bigger is better
bm = Basemap(llcrnrlat= llcrnrlat,
llcrnrlon= llcrnrlon,
urcrnrlat= urcrnrlat,
urcrnrlon= urcrnrlon,
ax = ax,
resolution='i', projection='tmerc', lon_0=-2, lat_0=49)
bm.fillcontinents(color='lightyellow', zorder=0)
bm.drawcoastlines(color='gray', linewidth=0.3, zorder=2)
plt.title('site_scores', fontsize=20)
# ======================
# make-up some locations
# ----------------------
n = 50 # you may use 121 here
lon1s = mid_lon + hr_lon*(np.random.random_sample(n)-0.5)
lat1s = mid_lat + hr_lat*(np.random.random_sample(n)-0.5)
# make-up list of 3-values data for the locations above
# -----------------------------------------------------
bar_data = np.random.randint(1,5,[n,3]) # list of 3 items lists
# create a barchart at each location in (lon1s,lat1s)
# ---------------------------------------------------
bar_width = 0.1 # inch
colors = ['r','y','b']
for ix, lon1, lat1 in zip(list(range(n)), lon1s, lat1s):
x1, y1 = bm(lon1, lat1) # get data coordinates for plotting
bax = build_bar(x1, y1, ax, 0.2, xvals=['a','b','c'], \
yvals=bar_data[ix], \
fcolors=colors)
# create legend (of the 3 classes)
patch0 = mpatches.Patch(color=colors[0], label='The 0-data')
patch1 = mpatches.Patch(color=colors[1], label='The 1-data')
patch2 = mpatches.Patch(color=colors[2], label='The 2-data')
ax.legend(handles=[patch0,patch1,patch2], loc=1)
plt.show()
情节将与此类似: