Tips for adjusting the appearance and fine adjustment of the graph generated by matplotlib (~ axis, picture frame, scale, scale character ~ edition).
We have confirmed the operation with matplotlib 3.2.2 and GoogleColab. (Python 3.6.9).
Install the japanize-matplotlib
library so that you can use ** Japanese ** in the graph. For Google Colab., You can install it by executing the following in the code cell.
japanize-Install matplotlib (Google Colab.)
!pip install japanize-matplotlib
Import various libraries.
Preparation / common code
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import matplotlib.transforms as transforms
import matplotlib.patheffects as patheffects
import japanize_matplotlib
import numpy as np
As a basic form, let's output a graph that has not been adjusted in particular.
Basic
x = np.linspace(-6,6,21)
y = 1/(1+np.exp(-x))
fig,ax = plt.subplots(figsize=(4,3),facecolor='white',dpi=150)
ax.plot(x,y,marker='.')
plt.show()
It is OK if the following graph can be output.
The format of the X-axis main scale is ** the format that displays up to the first decimal place , and the format of the Y-axis main scale is " 2.0 x 10 -1 " * Try setting it to "*".
Don't forget import matplotlib.ticker as ticker
.
Tick character formatting
x = np.linspace(-6,6,21)
y = 1/(1+np.exp(-x))
fig,ax = plt.subplots(figsize=(4,3),facecolor='white',dpi=150)
ax.plot(x,y,marker='.')
ax.xaxis.set_major_formatter(ticker.FuncFormatter(lambda x,_: f'{x:.1f}'))
ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda y,_: f'{y*10:.1f}'+ r'$\times 10^{-1}$'))
plt.show()
If you set the scale to "Inward" as described below, the X-axis and Y-axis scale characters may be too close together and unsightly. To solve this, try fine-tuning the character position on the X-axis main scale downward. Don't forget matplotlib.transforms as transforms
.
Adjusting the position of scale characters
x = np.linspace(1000,1010,11)
y = (x-1000)*0.5
fig,axes = plt.subplots(1,2,figsize=(8,3),facecolor='white',dpi=150)
axes = axes.ravel()
for ax in axes:
ax.plot(x,y,marker='.')
ax.set_xlim(1000,1010)
ax.set_ylim(0,5)
ax.tick_params(direction='in')
#Right side (axes[1]) Only xticklabels position adjustment
mv = transforms.ScaledTranslation(0,-0.07,fig.dpi_scale_trans)
for label in axes[1].xaxis.get_majorticklabels() :
label.set_transform(label.get_transform() + mv)
axes[1].text(0.95,0.075,'x_tick_labels with position adjustment',ha='right',c='tab:red',transform=ax.transAxes)
plt.show()
There was an easier way to get there.
Position adjustment of scale characters (updated version)
x = np.linspace(1000,1010,11)
y = (x-1000)*0.5
fig,axes = plt.subplots(1,2,figsize=(8,3),facecolor='white',dpi=150)
axes = axes.ravel()
for ax in axes:
ax.plot(x,y,marker='.')
ax.set_xlim(1000,1010)
ax.set_ylim(0,5)
ax.tick_params(direction='in')
#Right side (axes[1]) Only xticklabels position adjustment
ax = axes[1]
ax.get_xaxis().set_tick_params(pad=8)
ax.text(0.95,0.075,'x_tick_labels with position adjustment',ha='right',c='tab:red',transform=ax.transAxes)
plt.show()
If you use imshow (...)
etc., you may not want to display the axis / picture frame. Try hiding the axis / picture frame.
Hide axis / picture frame
x = np.linspace(-6,6,21)
y = 1/(1+np.exp(-x))
fig,ax = plt.subplots(figsize=(4,3),facecolor='white',dpi=150)
ax.plot(x,y,marker='.')
for p in ['left','top','right','bottom']:
ax.spines[p].set_visible(False)
ax.grid() #grid
plt.show()
Try changing the orientation of the axis scale to "inside", "outside", and "both sides". Also, try adjusting the "length" of the scale. You can effectively hide the tick marks by setting the length to zero.
Adjust the orientation and length of the scale
x = np.linspace(-6,6,21)
y = 10/(1+np.exp(-x))-5
fig,axes = plt.subplots(2,2,figsize=(8,6),facecolor='white',dpi=150)
axes = axes.ravel()
for ax in axes :
ax.plot(x,y,marker='.')
axes[0].tick_params(direction='in')
axes[0].text(0.1,0.9,"direction='in'",c='tab:red',va='top',transform=axes[0].transAxes)
axes[1].tick_params(direction='inout')
axes[1].text(0.1,0.9,"direction='inout'",c='tab:red',va='top',transform=axes[1].transAxes)
axes[2].tick_params(direction='inout',length=8)
axes[2].text(0.1,0.9,"direction='inout'\nlength=8",c='tab:red',va='top',transform=axes[2].transAxes)
axes[3].tick_params(length=0)
axes[3].text(0.1,0.9,"length=0",c='tab:red',va='top',transform=axes[3].transAxes)
plt.show()
You may want to change the color of only certain items in TickLabel to get the other person's attention. For now, let's just put Carol, the second element of xticklabels
, in red.
Change the color only for a specific scale character (TickLabel)
x = ['Alice','Bob','Carol','Dave','Ellen']
y = [40,20,25,40,20]
fig,ax = plt.subplots(figsize=(4,3),facecolor='white',dpi=150)
bars = ax.bar(x,y)
bars[2].set_facecolor('tab:red') #Bonus: Bar also changed to red
#print(type(bars[2])) # <class 'matplotlib.patches.Rectangle'>
labels = ax.get_xticklabels()
labels[2].set_color('tab:red') #Change the second element to red
#print(type(labels[2])) # <class 'matplotlib.text.Text'>
plt.show()
The Y-axis TickLabel is aligned from bottom to top by default. Let's flip it over and line it up from top to bottom.
Invert the Y-axis upside down
x = ['Alice','Bob','Carol','Dave','Ellen']
y = [40,20,25,40,20]
fig,axes = plt.subplots(1,2,figsize=(8,3),facecolor='white',dpi=150)
axes = axes.ravel()
for ax in axes:
ax.barh(x,y)
ax.tick_params(length=0)
ax.grid(axis='x')
ax.set_axisbelow(True)
axes[0].set_title('Default (bottom to top)')
axes[1].set_title('Invert (top to bottom)')
#Flip upside down in the figure on the right
ax = axes[1]
ax.invert_yaxis()
t = axes[1].text(0.95,0.05,'ax.invert_yaxis( )',c='tab:red',ha='right',transform=ax.transAxes)
t.set_path_effects([patheffects.Stroke(linewidth=3,foreground='white'),patheffects.Normal()])
plt.show()
Adjusted Y-axis scale label placement (right-aligned, left-aligned, center-aligned)
x = ['A','BB','CCC']
y = [40,20,25]
fig,axes = plt.subplots(3,1,figsize=(4,4),facecolor='white',dpi=150)
axes = axes.ravel()
text=['Right justified(Default)','Left justified','Centered']
for i, ax in enumerate(axes):
ax.barh(x,y)
ax.invert_yaxis()
ax.tick_params(length=0)
ax.set_xticklabels([])
t = ax.text(0.95,0.1,text[i],c='tab:red',ha='right',transform=ax.transAxes)
t.set_path_effects([patheffects.Stroke(linewidth=3,foreground='white'),patheffects.Normal()])
#Left justified
ax = axes[1]
ax.set_yticklabels(x,ha ='left')
ax.get_yaxis().set_tick_params(pad=25)
#Centered
ax = axes[2]
ax.set_yticklabels(x,ha ='center')
ax.get_yaxis().set_tick_params(pad=17.5)
plt.show()
Try changing to a graph style as described in math textbooks (the X-axis and Y-axis scale letters are in the "zero" position).
Set the X and Y axes to the zero position
x = np.linspace(-6,6,21)
y = 10/(1+np.exp(-x))-5 #Change
fig,ax = plt.subplots(figsize=(4,3),facecolor='white',dpi=150)
ax.plot(x,y,marker='.')
ax.spines['bottom'].set_position('zero')
ax.spines['left'].set_position('zero')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.tick_params(direction='inout')
plt.show()
In addition, make fine adjustments.
Set the X and Y axes to the zero position 2
x = np.linspace(-6,6,21)
y = 10/(1+np.exp(-x))-5 #Change
fig,ax = plt.subplots(figsize=(4,4),facecolor='white',dpi=150)
ax.plot(x,y,marker='.')
ax.spines['bottom'].set_position('zero')
ax.spines['left'].set_position('zero')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.set_xlim(6,-6)
ax.set_ylim(6,-6)
#Main scale: Notched intervals 2 and 0 are hidden, characters are bordered with white
ax.set_xticks(np.arange(-6,6+1,2))
labels = ax.set_xticklabels( [ ( x if x!=0 else '') for x in np.arange(-6,6+1,2)] )
for t in labels :
t.set_path_effects([patheffects.Stroke(linewidth=3,foreground='white'),patheffects.Normal()])
ax.set_yticks(np.arange(-6,6+1,2))
labels = ax.set_yticklabels( [ ( y if y!=0 else '') for y in np.arange(-6,6+1,2)] )
for t in labels :
t.set_path_effects([patheffects.Stroke(linewidth=3,foreground='white'),patheffects.Normal()])
ax.tick_params(which='major',direction='inout',length=5)
#Auxiliary scale (minor): Preparation for grid drawing with a step interval of 1
ax.set_xticks(np.linspace(-6,6,13),minor=True)
ax.set_yticks(np.linspace(-6,6,13),minor=True)
ax.tick_params(which='minor',direction='inout',length=3)
#Grid (which='both'And the grid at the major and minor scales)
ax.grid(which='both')
plt.show()
-(Matplotlib) I want to draw a graph with a size specified in pixels -I want to create a graph with wavy lines omitted in the middle with matplotlib (I want to manipulate the impression) -I want to output a beautifully customized heat map of the correlation matrix. matplotlib -(Visualization of correlation) Alternative when points overlap in scatter plot
Recommended Posts