To keep the colorbar aspect in subplot using cartopy, I insert new axis (add_axes) im my plot, but in adding, I need change the size of ticklabels colorbar and bold. But tick_params and set_yticklabels in not working in new axes.
# pos x, pos y, size x, size y
cb_ax = fig.add_axes([0.91, 0.302, 0.015, 0.383])
bar = fig.colorbar(img, cax=cb_ax, extend='max',
shrink=0.8, pad=0.0, spacing='uniform',
orientation='vertical', ticks=clevs,
extendfrac='auto')
bar.set_label(label=f'(mm)', size=10, weight='bold')
# not working
# bar.tick_params(labelsize=10)
# not working
# bar.img.set_yticklabels(clevs, fontsize=9, weight='bold')
Entire code: https://pastebin.com/NfiMWf2n
Plot result: https://1drv.ms/u/s!Amb6LUmV4LnKi55gRf6DqGDKjfTGxA?e=HCGeZb
You can set the weight and fontsize of bar.ax:
import matplotlib.pyplot as plt
import numpy as np
fig=plt.figure()
img = plt.imshow(np.random.random((4,4)))
cb_ax = fig.add_axes([0.91, 0.302, 0.015, 0.383])
bar = fig.colorbar(img, cax=cb_ax, extend='max',
shrink=0.8, pad=0.0, spacing='uniform',
orientation='vertical',
extendfrac='auto')
fig.canvas.flush_events() #else bar.ax.get_yticklabels() is not yet updated
bar.ax.set_yticklabels(labels=bar.ax.get_yticklabels(), weight='bold', fontsize=5)
bar.set_label(label=f'(mm)', size=10, weight='bold')
Output:
Related
My colorbar is very far away from the bottom of my heatmap. Is there a way to move it closer?
My code is:
import seaborn as sns
Granger2 = Granger
Granger2.columns = Granger_colnames
Granger2.index = Granger_rownames
fig, ax = plt.subplots(figsize=(6,25))
sns.heatmap(Granger2, cmap=rvb, cbar=True, ax=ax,linewidths=.5,cbar_kws={"orientation": "horizontal"})
ax.xaxis.tick_top() # x axis on top
ax.xaxis.set_label_position('top')
#Remove ticks
ax.tick_params(axis='both', which='both', length=0)
# Drawing the frame
ax.axhline(y = 0, color='k',linewidth = 1)
ax.axhline(y = Granger2.shape[0], color = 'k',linewidth = 1)
ax.axvline(x = 0, color = 'k', linewidth = 1)
ax.axvline(x = Granger2.shape[1], color = 'k', linewidth = 1)
plt.show()
You can use e.g. cbar_kws={"orientation": "horizontal", "pad":0.02}. The padding is a fraction of the subplot height, so 0.02 is 2%. See the colorbar docs for more information about pad and other parameters.
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
sns.set_style('whitegrid')
flights = sns.load_dataset('flights')
flights = flights.pivot('year', 'month').droplevel(0, axis=1)
fig, ax = plt.subplots(figsize=(6, 20))
sns.heatmap(flights, cmap='Greens', cbar=True, ax=ax, linewidths=.5,
cbar_kws={"orientation": "horizontal", "pad": 0.02})
ax.xaxis.tick_top() # x axis on top
ax.xaxis.set_label_position('top')
# Remove ticks
ax.tick_params(axis='both', which='both', length=0)
# Drawing the frame
ax.patch.set_edgecolor('0.15')
ax.patch.set_linewidth(2)
plt.tight_layout()
plt.show()
I'm trying to control the zorder of different plots across twinx axes. How can I get the blue noisy plots to appear in the background and the orange smoothed plots to appear in the foreground in this plot?
from matplotlib import pyplot as plt
import numpy as np
from scipy.signal import savgol_filter
random = np.random.RandomState(0)
x1 = np.linspace(-10,10,500)**3 + random.normal(0, 100, size=500)
x2 = np.linspace(-10,10,500)**2 + random.normal(0, 100, size=500)
fig,ax1 = plt.subplots()
ax1.plot(x1, zorder=0)
ax1.plot(savgol_filter(x1,99,2), zorder=1)
ax2 = ax1.twinx()
ax2.plot(x2, zorder=0)
ax2.plot(savgol_filter(x2,99,2), zorder=1)
plt.show()
Similar to this thread, though not ideal, this is an approach using twiny along with twinx.
# set up plots
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
ax3 = ax1.twiny()
ax4 = ax2.twiny()
# background
ax1.plot(x1)
ax2.plot(x2)
# smoothed
ax3.plot(savgol_filter(x1,99,2), c='orange')
ax4.plot(savgol_filter(x2,99,2), c='orange')
# turn off extra ticks and labels
ax3.tick_params(axis='x', which='both', bottom=False, top=False)
ax4.tick_params(axis='x', which='both', bottom=False, top=False)
ax3.set_xticklabels([])
ax4.set_xticklabels([])
# fix zorder
ax1.set_zorder(1)
ax2.set_zorder(2)
ax3.set_zorder(3)
ax4.set_zorder(4)
plt.show()
Output:
I would like to set some space between the image and the colorbar, I have tried the pad but do nothing, so...
This is the image I have:
and this is the code:
from mpl_toolkits.axes_grid1 import make_axes_locatable
from matplotlib.colors import LogNorm
from matplotlib.ticker import LogLocator
from matplotlib import rcParams
rcParams['font.size']=35
x = np.arange(0,16,1)
yx= np.linspace(-50,0,38)
mx = np.random.rand(15,38)
m2 = np.linspace(0,6,38)
fig, ax = plt.subplots(figsize=(40,30))
divider = make_axes_locatable(ax)
cax = divider.append_axes('right', size='5%', pad=2)
im = ax.pcolor(x,yx,mx.T,norm=LogNorm(0.1, 100),cmap= 'jet')
cbar = fig.colorbar(im,pad = 2,cax=cax, orientation='vertical')
cbar.ax.yaxis.set_major_locator(LogLocator()) # <- Why? See above.
cbar.ax.set_ylabel('Resistividade \u03C1 [ohm.m]', rotation=270)
ax2=ax.twiny()
ax2.plot(m2,yx,'k--',linewidth=10)
#ax2.set_xlim([0,60])
ax2.set_xlabel('Resistividade \u03C1 [ohm.m]')
ax.set_xlabel('Aquisição')
ax.set_ylabel('Profundidade [m]')
#fig.tight_layout()
plt.savefig('mrec_1'+'.png',bbox_inches = "tight", format='png', dpi=300)
plt.show()
The secondary axes occupies all of the space in the figure that is meant for axes. Therefore, no matter what padding you give to the colorbar of ax, it wont affect ax2.
A hacky-ish solution would be to also spit your secondary axes exactly the same as the primary axes, and then delete the axes where the second colorbar goes:
fig, ax = plt.subplots(figsize=(10, 8))
pad = 0.2 # change the padding. Will affect both axes
im = ax.pcolor(x, yx, mx.T, norm=LogNorm(0.1, 100), cmap='jet')
divider = make_axes_locatable(ax)
cax = divider.append_axes('right', size='5%', pad=pad)
ax2 = ax.twiny()
ax2.plot(m2, yx, 'k--', linewidth=10)
ax2.set_xlim([0, 60])
ax2.set_xlabel('Resistividade \u03C1 [ohm.m]')
ax.set_xlabel('Aquisição')
ax.set_ylabel('Profundidade [m]')
cbar = fig.colorbar(im,pad = 2,cax=cax, orientation='vertical')
cbar.ax.yaxis.set_major_locator(LogLocator())
cbar.ax.set_ylabel('Resistividade \u03C1 [ohm.m]', rotation=270)
secondary_divider = make_axes_locatable(ax2) # divide second axes
redundant_cax = secondary_divider.append_axes('right', size='5%', pad=pad)
redundant_cax.remove() # delete the second (empty) colorbar
plt.show()
I would like to add a sample y-axis tick on the right side of the Ridge plot, to know what is the range of values of all the plots. Preferably I would like to add it only to one of the subplots and not to all of them.
My plot is based on the seaborn 'ridge plot' example at: https://seaborn.pydata.org/examples/kde_ridgeplot.html
I've tried the following code with no luck:
g.set(yticks=[0,200])
g.set_y_label_position("right")
g.set_ylabels('[Range]',fontsize=9,fontweight="normal")
If you want to modify one particular axes from a FacetGrid, you can get a reference from the list g.axes
Here is how I would go about it
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
sns.set(style="white", rc={"axes.facecolor": (0, 0, 0, 0)})
# Create the data
rs = np.random.RandomState(1979)
x = rs.randn(500)
g = np.tile(list("ABCDEFGHIJ"), 50)
df = pd.DataFrame(dict(x=x, g=g))
m = df.g.map(ord)
df["x"] += m
# Initialize the FacetGrid object
pal = sns.cubehelix_palette(10, rot=-.25, light=.7)
g = sns.FacetGrid(df, row="g", hue="g", aspect=15, height=.5, palette=pal)
# Draw the densities in a few steps
g.map(sns.kdeplot, "x", clip_on=False, shade=True, alpha=1, lw=1.5, bw=.2)
g.map(sns.kdeplot, "x", clip_on=False, color="w", lw=2, bw=.2)
g.map(plt.axhline, y=0, lw=2, clip_on=False)
# Define and use a simple function to label the plot in axes coordinates
def label(x, color, label):
ax = plt.gca()
ax.text(0, .2, label, fontweight="bold", color=color,
ha="left", va="center", transform=ax.transAxes)
g.map(label, "x")
#
# Changes from seaborn example below this point
#
# Set the subplots to overlap
g.fig.subplots_adjust(hspace=-.25, right=0.9)
# Remove axes details that don't play well with overlap
g.set_titles("")
#g.set(yticks=[])
g.despine(bottom=True, left=True, right=False, top=True, offset=5)
for ax in g.axes.ravel():
if ax.is_first_row(): # can use .is_last_row() to show spine on the bottom plot instead
ax.yaxis.tick_right()
ax.yaxis.set_label_position("right")
ax.set_ylabel("MW")
else:
ax.spines['right'].set_visible(False)
[l.set_visible(False) for l in ax.get_yticklabels()] # necessary because y-axes are shared
I'd like to create a colorbar legend for a heatmap, such that the labels are in the center of each discrete color. Example borrowed from here:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import ListedColormap
#discrete color scheme
cMap = ListedColormap(['white', 'green', 'blue','red'])
#data
np.random.seed(42)
data = np.random.rand(4, 4)
fig, ax = plt.subplots()
heatmap = ax.pcolor(data, cmap=cMap)
#legend
cbar = plt.colorbar(heatmap)
cbar.ax.set_yticklabels(['0','1','2','>3'])
cbar.set_label('# of contacts', rotation=270)
# put the major ticks at the middle of each cell
ax.set_xticks(np.arange(data.shape[1]) + 0.5, minor=False)
ax.set_yticks(np.arange(data.shape[0]) + 0.5, minor=False)
ax.invert_yaxis()
#labels
column_labels = list('ABCD')
row_labels = list('WXYZ')
ax.set_xticklabels(column_labels, minor=False)
ax.set_yticklabels(row_labels, minor=False)
plt.show()
This generates the following plot:
Ideally I'd like to generate a legend bar which has the four colors and for each color, a label in its center: 0,1,2,>3. How can this be achieved?
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import ListedColormap
#discrete color scheme
cMap = ListedColormap(['white', 'green', 'blue','red'])
#data
np.random.seed(42)
data = np.random.rand(4, 4)
fig, ax = plt.subplots()
heatmap = ax.pcolor(data, cmap=cMap)
#legend
cbar = plt.colorbar(heatmap)
cbar.ax.get_yaxis().set_ticks([])
for j, lab in enumerate(['$0$','$1$','$2$','$>3$']):
cbar.ax.text(.5, (2 * j + 1) / 8.0, lab, ha='center', va='center')
cbar.ax.get_yaxis().labelpad = 15
cbar.ax.set_ylabel('# of contacts', rotation=270)
# put the major ticks at the middle of each cell
ax.set_xticks(np.arange(data.shape[1]) + 0.5, minor=False)
ax.set_yticks(np.arange(data.shape[0]) + 0.5, minor=False)
ax.invert_yaxis()
#labels
column_labels = list('ABCD')
row_labels = list('WXYZ')
ax.set_xticklabels(column_labels, minor=False)
ax.set_yticklabels(row_labels, minor=False)
plt.show()
You were very close. Once you have a reference to the color bar axis, you can do what ever you want to it, including putting text labels in the middle. You might want to play with the formatting to make it more visible.
To add to tacaswell's answer, the colorbar() function has an optional cax input you can use to pass an axis on which the colorbar should be drawn. If you are using that input, you can directly set a label using that axis.
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
fig, ax = plt.subplots()
heatmap = ax.imshow(data)
divider = make_axes_locatable(ax)
cax = divider.append_axes('bottom', size='10%', pad=0.6)
cb = fig.colorbar(heatmap, cax=cax, orientation='horizontal')
cax.set_xlabel('data label') # cax == cb.ax
This will make you add label and change colorbar's tick and label size:
clb=plt.colorbar()
clb.ax.tick_params(labelsize=8)
clb.ax.set_title('Your Label',fontsize=8)
This can be also used if you have sublots:
plt.tight_layout()
plt.subplots_adjust(bottom=0.05)
cax = plt.axes([0.1, 0, 0.8, 0.01]) #Left,bottom, length, width
clb=plt.colorbar(cax=cax,orientation="horizontal")
clb.ax.tick_params(labelsize=8)
clb.ax.set_title('Your Label',fontsize=8)