Reputation: 17
i have the following code and somehow i can not place the colorbar in such a place that it is not overlapping with the imshow itself and if I place it further outside it is cutted off :( I tried already a lot of things, but nothing worked for this problem. If the colorbar is not horizontal that would work for me, too, but then the label of the axis need to be perpendicular too.
HELP
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
vegetables = [ "One magnet", "Two magnets","washer",
"ST37 - 1", "ST37 - 2", "ST37 - 3", "RVS"]
farmers0 = ["1 cm/s", "1.25 cm/s"]
mask0 = np.array([[False, False, False, False, False, False, False],
[False, False, False, True, True, True, True]])
harvest1 = np.array([[ 1.9, 1.6,1.1,1.2,1.1,0.5,0.7],
[ 1.6, 0.8,0.9, 0,0,0,0]])
harvest1 = np.ma.array(harvest1, mask=mask0)
harvest2 = np.array([[ 0.9, 1.0,0.7,1.0,1.1,0.4,0.6],
[ 0.9, 0.8,0.8, 0,0,0,0]])
harvest2 = np.ma.array(harvest2, mask=mask0)
fig, ax = plt.subplots(2, sharex=True, sharey=False)
im0 = ax[0].imshow(harvest1, cmap='RdYlGn_r', vmin = 0.5, vmax = 1.65)
# We want to show all ticks...
ax[0].set_xticks(np.arange(len(vegetables)))
ax[0].set_yticks(np.arange(len(farmers0)))
# ... and label them with the respective list entries
ax[0].set_xticklabels(vegetables)
ax[0].set_yticklabels(farmers0)
# Rotate the tick labels and set their alignment.
plt.setp(ax[0].get_xticklabels(), rotation=45, ha="right",
rotation_mode="anchor")
for i in range(len(farmers0)):
for j in range(len(vegetables)):
text = ax[0].text(j, i, harvest1[i, j],
ha="center", va="center", color="k")
im0 = ax[1].imshow(harvest2, cmap='RdYlGn_r', vmin = 0.5, vmax = 1.65)
# We want to show all ticks...
ax[1].set_xticks(np.arange(len(vegetables)))
ax[1].set_yticks(np.arange(len(farmers0)))
# ... and label them with the respective list entries
ax[1].set_xticklabels(vegetables)
ax[1].set_yticklabels(farmers0)
# Rotate the tick labels and set their alignment.
plt.setp(ax[1].get_xticklabels(), rotation=45, ha="right",
rotation_mode="anchor")
for i in range(len(farmers0)):
for j in range(len(vegetables)):
text = ax[1].text(j, i, harvest2[i, j],
ha="center", va="center", color="k")
#fig.colorbar(im0, ax=ax.ravel().tolist(), orientation = 'horizontal')
#plt.gcf().subplots_adjust(top=1.5)
fig.tight_layout()
cbaxes = fig.add_axes([0.15,0.9,0.82,0.05]) #links, hight
#cax = divider.append.axes("bottom", size= "5%", pad = 0.05)
bar2 = plt.colorbar(im0, cax = cbaxes , orientation = 'horizontal')
bar2.ax.set_title('90 % confidence interval of $d$')
plt.show()
Upvotes: 1
Views: 162
Reputation: 2970
here's a version that uses GridSpec
to get more control over the axis-grid (e.g. so you can adjust the spacing between colorbar and axes etc.)
also note that i use aspect='auto'
in the ax.imshow
calls to allow non-square pixels!
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec, GridSpecFromSubplotSpec
vegetables = [ "One magnet", "Two magnets","washer",
"ST37 - 1", "ST37 - 2", "ST37 - 3", "RVS"]
farmers0 = ["1 cm/s", "1.25 cm/s"]
mask0 = np.array([[False, False, False, False, False, False, False],
[False, False, False, True, True, True, True]])
harvest1 = np.array([[ 1.9, 1.6,1.1,1.2,1.1,0.5,0.7],
[ 1.6, 0.8,0.9, 0,0,0,0]])
harvest1 = np.ma.array(harvest1, mask=mask0)
harvest2 = np.array([[ 0.9, 1.0,0.7,1.0,1.1,0.4,0.6],
[ 0.9, 0.8,0.8, 0,0,0,0]])
harvest2 = np.ma.array(harvest2, mask=mask0)
# -----------------------------------------------
# manually create an axes to have full control over spacing etc.
gs = GridSpec(2, 1,
height_ratios=(.5, 9.5))
gs_ax = GridSpecFromSubplotSpec(2, 1, gs[1],
hspace=.5)
fig = plt.figure(figsize=(7, 7))
ax = []
ax.append(fig.add_subplot(gs_ax[0]))
ax.append(fig.add_subplot(gs_ax[1]))
cbaxes = fig.add_subplot(gs[0])
# manually ensure that x- and y- axes are shared
ax[0].get_shared_x_axes().join(ax[1])
ax[0].get_shared_y_axes().join(ax[1])
# -----------------------------------------------
im0 = ax[0].imshow(harvest1, cmap='RdYlGn_r', vmin = 0.5, vmax = 1.65,
aspect="auto")
# We want to show all ticks...
ax[0].set_xticks(np.arange(len(vegetables)))
ax[0].set_yticks(np.arange(len(farmers0)))
# ... and label them with the respective list entries
ax[0].set_xticklabels(vegetables)
ax[0].set_yticklabels(farmers0)
# Rotate the tick labels and set their alignment.
plt.setp(ax[0].get_xticklabels(), rotation=45, ha="right",
rotation_mode="anchor")
for i in range(len(farmers0)):
for j in range(len(vegetables)):
text = ax[0].text(j, i, harvest1[i, j],
ha="center", va="center", color="k")
im0 = ax[1].imshow(harvest2, cmap='RdYlGn_r', vmin = 0.5, vmax = 1.65,
aspect="auto")
# We want to show all ticks...
ax[1].set_xticks(np.arange(len(vegetables)))
ax[1].set_yticks(np.arange(len(farmers0)))
# ... and label them with the respective list entries
ax[1].set_xticklabels(vegetables)
ax[1].set_yticklabels(farmers0)
# Rotate the tick labels and set their alignment.
plt.setp(ax[1].get_xticklabels(), rotation=45, ha="right",
rotation_mode="anchor")
for i in range(len(farmers0)):
for j in range(len(vegetables)):
text = ax[1].text(j, i, harvest2[i, j],
ha="center", va="center", color="k")
#cax = divider.append.axes("bottom", size= "5%", pad = 0.05)
bar2 = plt.colorbar(im0, cax = cbaxes , orientation = 'horizontal')
bar2.ax.set_title('90 % confidence interval of $d$')
fig.tight_layout()
plt.show()
Upvotes: 1
Reputation: 2970
matplotlib actually warns you that tight_layout
will not work with manually added axes...
UserWarning: This figure includes Axes that are not compatible with tight_layout, so results might be incorrect. fig.tight_layout()
use fig.subplots_adjust
to set the boundaries of your plot manually!
so basically... just add this line at the very end and you're fine :-)
fig.tight_layout()
fig.subplots_adjust(top=0.8)
and maybe also explicitly specify the figure-size by changing your call to plt.subplots
to:
fig, ax = plt.subplots(2, figsize=(7, 5), sharex=True, sharey=False)
Upvotes: 2