In seaborn, how can you change just the x and y axis label font size? Instead of using the "set context" method, is there a way to specifically change just the axis labels? Here is my code:
def corrfunc(x, y, **kws):
r = stats.pearsonr(x, y)[0] ** 2
ax = plt.gca()
ax.annotate("r$^2$ = {:.2f}".format(r),
xy=(.1, .9), xycoords=ax.transAxes, fontsize=16)
if r > 0.6:
col = 'g'
elif r < 0.6:
col = 'r'
sns.regplot(x, y, color=col)
return r
IC_Plot = sns.PairGrid(df_IC, palette=["red"])
IC_Plot.map_offdiag(corrfunc)
IC_Plot.savefig("Save_Pair.png")
The easiest way to change the fontsize of all x- and y- labels in a plot is to use the rcParams property "axes.labelsize" at the beginning of the script, e.g.
plt.rcParams["axes.labelsize"] = 15
You may also set the font size of each individual label
for ax in plt.gcf().axes:
l = ax.get_xlabel()
ax.set_xlabel(l, fontsize=15)
Related
I want to use matpoltlib to make a plot that with a constant y axis(always from 0 to 14 and the gap is 1), since I want to make labels for them and my dot values will be(x, y) where y is from 0 to 14 gap 1, and a changing x axis. I already tried to play with y ticks. And here is my code for that:
fig, ax = plt.subplots()
fig.canvas.draw()
plt.yticks(np.arange(0, 14, 1))
labels = [item.get_text() for item in ax.get_yticklabels()]
labels[1] = 'Not Detected'
labels[2] = 'A/G'
labels[3] = 'G/G'
labels[4] = 'C/T'
labels[5] = 'C/C'
labels[6] = 'A/A'
labels[7] = '-1'
labels[8] = 'ε3/ε3'
labels[9] = 'A/C'
labels[10] = 'T/T'
labels[11] = 'C/G'
labels[12] = 'ε2/ε3'
labels[13] = 'G/T'
ax.set_yticklabels(labels)
what I'm thinking about is to use some values or lines with white color so those y axis will appear. But I'm looking for a more efficient way of doing it. And here is the diagram I generated with the current code. It only shows C/C right now and I want all labels to appear in the diagram.
I tried draw white points with:
x1 = np.arange(n)
y1 = np.arange(1,15,1)
plt.scatter(x1,y1,color = 'white')
Which did give me what I want: But I was wondering whether there is a lib setting that can do this.
I would recommend just using a fixed locator and fixed formatter for your y axis. The function, ax.set_yticklabels() is simply a convenience wrapper for these tick methods.
I would also recommend having your y_labels in a list or using a loop structure as this is a more generalizable and modifiable implementation.
If I'm understanding the goals of your plot correctly, something like this may work well for you.
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
#make some data
x = np.arange(25)
y = np.random.randint(1, 14, size=25)
#convert y labels to a list
y_labels = [
'Not Detected','A/G','G/G','C/T','C/C','A/A',
'-1','ε3/ε3', 'A/C','T/T','C/G','ε2/ε3','G/T'
]
#define figure/ax and set figsize
fig, ax = plt.subplots(figsize=(12,8))
#plot data, s is marker size, it's points squared
ax.scatter(x, y, marker='x', s=10**2, color='#5d2287', linewidth=2)
#set major locator and formatter to fixed, add grid, hide top/right spines
locator = ax.yaxis.set_major_locator(mpl.ticker.FixedLocator(np.arange(1, 14)))
formatter = ax.yaxis.set_major_formatter(mpl.ticker.FixedFormatter(y_labels))
grid = ax.grid(axis='y', dashes=(8,3), alpha=0.3, color='gray')
spines = [ax.spines[x].set_visible(False) for x in ['top','right']]
params = ax.tick_params(labelsize=12) #increase label font size
I'm creating some subplots each with its own colorbar at the bottom. The colorbar is added using:
cax, kw = mcbar.make_axes_gridspec(ax, orientation='horizontal',
pad=pad,
fraction=0.07, shrink=0.85, aspect=35)
figure.colorbar(cs, cax=cax, orientation='horizontal')
The pad argument is adjusted, so that if there is no xticklabels, the value is smaller, to avoid wasting space.
The complete script:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colorbar as mcbar
x = np.linspace(-1, 1, 100)
y = np.linspace(-1, 1, 50)
X, Y = np.meshgrid(x, y)
Z = X**2+np.sin(Y)
figure = plt.figure(figsize=(12, 10))
nrow = 3
ncol = 2
for ii in range(nrow*ncol):
ax = figure.add_subplot(nrow, ncol, ii+1)
row, col = np.unravel_index(ii, (nrow, ncol))
cs = ax.contourf(X, Y, Z)
if row == nrow-1:
# larger padding to make room for xticklabels
pad = 0.15
else:
# smaller padding otherwise
pad = 0.05
ax.tick_params(labelbottom=False)
if row == 1 and col == 1:
# add xlabel would need more padding
ax.set_xlabel('X')
cax, kw = mcbar.make_axes_gridspec(ax, orientation='horizontal',
pad=pad,
fraction=0.07, shrink=0.85, aspect=35)
figure.colorbar(cs, cax=cax, orientation='horizontal')
ax.set_title(str(ii+1))
figure.tight_layout()
figure.show()
The output figure:
But the current solution is using hard-coded padding values (0.15 if with xticklabels, 0.05 otherwise), and it doesn't adjust well to the existence of xlabels (see subplot 4), or changing figure sizes.
Is there a way to programmatically work out a suitable padding value to place the colorbar? Maybe by adjusting the bounding box of the parent axis object so that its bbox is smaller if there is no xlabels or xticklabels, or by finding out the coordinates of the parent axis and somehow computing a padding?
You can get the space needed for tick labels and the axis label by comparing the bounding boxes of the whole axes and the yaxis. To get these bounding boxes we need a renderer. To make it available we first need to draw the canvas. The bounding boxes are returned in display coordinates, so we transform them to axes coordinates using the inverted axes transformation. The difference of their y coordinates gives the required extra padding:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colorbar as mcbar
from matplotlib.transforms import Bbox
x = np.linspace(-1, 1, 100)
y = np.linspace(-1, 1, 50)
X, Y = np.meshgrid(x, y)
Z = X**2+np.sin(Y)
figure = plt.figure(figsize=(12, 10))
figure.canvas.draw() # to get renderer
nrow = 3
ncol = 2
for ii in range(nrow*ncol):
ax = figure.add_subplot(nrow, ncol, ii+1)
row, col = np.unravel_index(ii, (nrow, ncol))
cs = ax.contourf(X, Y, Z)
if row != nrow-1:
ax.tick_params(labelbottom=False)
if row == 1 and col == 1:
# add xlabel would need more padding
ax.set_xlabel('X')
# get height of ticklabels and label
b = ax.transAxes.inverted().transform(
[ax.yaxis.get_tightbbox(figure.canvas.renderer).p0,
ax.get_tightbbox(figure.canvas.renderer).p0]
)
pad = 0.05 + (b[0]-b[1])[1]
cax, kw = mcbar.make_axes_gridspec(ax, orientation='horizontal',
pad=pad,
fraction=0.07, shrink=0.85, aspect=35)
figure.colorbar(cs, cax=cax, orientation='horizontal')
ax.set_title(str(ii+1))
This solution has the flaw that axes 3 and 4 have different heights. You can fix this by adjusting ymin of all axes in a row to the row maximum:
figure.tight_layout()
for i in range(0, 2*ncol*nrow, 2*ncol):
ymin = 0
for j in range(0, 2*ncol, 2):
ymin = max(ymin, figure.axes[i+j].get_position().ymin)
for j in range(0, 2*ncol, 2):
b = figure.axes[i+j].get_position()
figure.axes[i+j].set_position(Bbox([[b.xmin,ymin],[b.xmax,b.ymax]]))
Please note that this adjustment must be done before applying tight_layout!
I would like to display an histogram with bars in different colors according to a condition.
I mean, I would like to set bars which are between 2 and 5 in a different color.
I've tried this:
bins = np.linspace(0, 20, 21)
lista_float_C1 = [1,1,1,2,2,2,3,4,4,5,5,6,7,8,8,8,8,10,11,11]
colors = []
y = plt.hist(lista_float_C1, bins, alpha=0.5 )
for x in y[1]:
if (x >= 2)&(x=<5):
colors.append('r')
else:
colors.append('b')
print(colors)
plt.hist(lista_float_C1, bins, alpha=0.5, color = colors )
plt.show()
I get this error :
color kwarg must have one color per data set. 1 data sets and 21 colors were provided
You can modify the patches after you plot them:
lista_float_C1 = [1,1,1,2,2,2,3,4,4,5,5,6,7,8,8,8,8,10,11,11]
fig,ax = plt.subplots()
ax.hist(lista_float_C1, bins, alpha=0.5 )
for p in ax.patches:
x = p.get_height()
# modify this to fit your needs
color = 'r' if (2<=x<=5) else 'b'
p.set_facecolor(color)
plt.show()
plt.show()
Output:
If you want to color by bin values:
for p in ax.patches:
# changes here
x,y = p.get_xy()
color = 'r' if (2<=x<=5) else 'b'
p.set_facecolor(color)
plt.show()
Output:
I'm coding with python.
I have 3 arrays x, y and z, and I would like to do 2d density map of the z values in the plan (x,y) with colorbar.
So in my plot, the color at the point x[0] and y[0] would be determined by the value of z[0], the color at the point x[1] and y[1] would be determined by the value of z[1], etc.
Does anyone know how to do this ?
Thank you
Check out https://matplotlib.org/api/_as_gen/matplotlib.pyplot.scatter.html
For different colormaps: https://matplotlib.org/tutorials/colors/colormaps.html
A sample piece of code for your need will be something like this
#--------------------------Plotting starts here---------------------------------#
fig, ax0 = plt.subplots()
im0 = plt.scatter(x,y,s=1,c=z, cmap='bwr')
#------------------if you want to use pcolormesh-------------------
#----------and have Z values stored as a numpy array Data---------------------#
#X,Y = np.meshgrid(x,y)
#im0 = ax0.pcolormesh(X,Y,Data, cmap="YourFavouriteColormap')
cbar = fig.colorbar(im0,ax=ax0)
ax0.set_title("Your title")
plt.xlabel("xlabel")
plt.ylabel("ylabel")
filename = "prefix" + "."+ "fileformat"
plt.savefig(filename)
Edit 1:
From one of your comments, if you have grid data, you can try pcolormesh and try shading, an optional argument for interpolation.
shading{'flat', 'gouraud'}, optional
The fill style, Possible values:
'flat': A solid color is used for each quad. The color of the quad (i, j), (i+1, j), (i, j+1), (i+1, j+1) is given by C[i, j].
'gouraud': Each quad will be Gouraud shaded: The color of the corners (i', j') are given by C[i',j']. The color values of the area in between is interpolated from the corner values. When Gouraud shading is used, edgecolors is ignored.
You can use matplotlib's scatter plots with legends and grid where the size of each circle can be referred to z values. This is an example I got from here:
volume = np.random.rayleigh(27, size=40)
amount = np.random.poisson(10, size=40)
ranking = np.random.normal(size=40)
price = np.random.uniform(1, 10, size=40)
fig, ax = plt.subplots()
scatter = ax.scatter(volume, amount, c=ranking, s=0.3*(price*3)**2,
vmin=-3, vmax=3, cmap="Spectral")
legend1 = ax.legend(*scatter.legend_elements(num=5),
loc="upper left", title="Ranking")
ax.add_artist(legend1)
kw = dict(prop="sizes", num=5, color=scatter.cmap(0.7), fmt="$ {x:.2f}",
func=lambda s: np.sqrt(s/.3)/3)
legend2 = ax.legend(*scatter.legend_elements(**kw),
loc="lower right", title="Price")
plt.show()
Output:
In response to your comment AshlinJP :
Either way I still got the error message : "imshow() got multiple values for keyword argument 'cmap'"
I don't know if it has any importance but I use python 2.7
Actually my code is :
import numpy as np
import matplotlib.pyplot as plt
x,y,z = np.loadtxt('gamma.txt', unpack = True)
fig, ax0 = plt.subplots()
cmap = plt.get_cmap('viridis')
im0 = ax0.imshow(x,y,z, cmap=cmap, interpolation="gaussian")
cbar = fig.colorbar(im0,ax=ax0)
ax0.set_title("Your title")
plt.xlabel("xlabel")
plt.ylabel("ylabel")
This question already has answers here:
Aligning rotated xticklabels with their respective xticks
(5 answers)
Closed 4 months ago.
I am making a bar chart and I want to move the x-axis tick labels one position to left. Here is the code of the plot:
matplotlib.rcParams.update(matplotlib.rcParamsDefault)
plt.style.use(['seaborn-white', 'bmh'])
fig1, ax = plt.subplots()
palette = ['#2a5495', '#07a64c', '#e979ad', '#d88432', '#2a5495',
'#b7040e', '#82c5db', '#b9c09b', '#cd065d', '#4b117f']
x = np.array(df.index)
y = np.array(df.loc[:, 2015])
width = 1.0
lefts = [x * width for x, _ in enumerate(y)]
ax.bar(left = lefts, height = y, width = width, tick_label = x, color = palette, label = ranked_univs)
ax.axis(ymin = 0, ymax = 200, xmin = -0.5, xmax = 9.5)
ax.tick_params(axis='x', which='major', labelsize=8)
ax.set_xticklabels(ax.xaxis.get_majorticklabels(), rotation=45)
fig1.tight_layout()
plt.show()
And here is the bar chart:
Any clue?
Your labels are correctly positioned, as shown by the fact that if you were to rotate them 90°, they would be perfectly aligned with your bars.
fig1, ax = plt.subplots()
palette = ['#2a5495', '#07a64c', '#e979ad', '#d88432', '#2a5495',
'#b7040e', '#82c5db', '#b9c09b', '#cd065d', '#4b117f']
labels = ['Long misaligned label {}'.format(i) for i in range(10)]
x = range(10)
y = 100+100*np.random.random((10,))
width = 1.0
lefts = [x * width for x, _ in enumerate(y)]
ax.bar(left = lefts, height = y, width = width, tick_label = labels, color = palette)
ax.axis(ymin = 0, ymax = 200, xmin = -0.5, xmax = 9.5)
ax.tick_params(axis='x', which='major', labelsize=8)
ax.set_xticklabels(ax.xaxis.get_majorticklabels(), rotation=90)
fig1.tight_layout()
plt.show()
The problem is that the labels are centered horizontally, so when you rotate them 45°, they appear to be aligned with the wrong bar. To fix this, align the labels to the right, and they'll get back to their correct (visual) position.
plt.setp(ax.xaxis.get_majorticklabels(), ha='right')
Another (maybe simpler) option is to use the helper function Figure.autofmt_xdate(), which handles all of this for you.
See this question: How can I rotate xticklabels in matplotlib so that the spacing between each xticklabel is equal?
There the solution is to align the labels to their right side:
ax.set_xticklabels(xticklabels, rotation = 45, ha="right")