I'm trying to personalize some of my graphs so I'd like to change the font of all axis. I wrote the code below for that. The problem is that I can't change the font of the z axis. Somebody have a recommendation?
Thanks in advance.
import matplotlib.pyplot as plt
from matplotlib import cm
font = {'size' : 12}
cm=1/2.54
size_x = 10*cm
size_y = 8*cm
min_limx = 4
max_limx = 10
min_limy = 0
max_limy = 50
min_limz = 0
max_limz = 8
#%%
fig, ax = plt.subplots(figsize=(size_x, size_y), subplot_kw={"projection": "3d"})
X, Y = np.meshgrid(xnew, ynew, indexing='ij')
Z1 = m_fill
Z2 = m_nofill
surf = ax.plot_surface(X, Y, Z1, cmap=cm.viridis, linewidth=0, antialiased=False)
surf = ax.plot_surface(X, Y, Z2, color='w', linewidth=0, antialiased=False)
ax.set_xlabel('$\lambda$', **font)
ax.set_ylabel('$\chi$', **font)
ax.set_zlabel('$\it{m_{0}, кг}$', **font)
lin_x = np.arange(min_limx, max_limx, step=2)
lin_y = np.arange(min_limy, max_limy, step=15)
plt.xticks(lin_x, **font)
plt.yticks(lin_y, **font)
#plt.zticks(lin_z, **font) # AttributeError: module 'matplotlib.pyplot' has no attribute 'zticks'
ax.set_zlim(0, 8, )
#plt.gca().set_aspect('equal', adjustable='box')
ax.view_init(45, -45)
#plt.tight_layout()
plt.grid()
plt.show()
fig.savefig('p0_V_m0.png', format='png', dpi=300)
Ps: This is how the figure looks like right now.
The fontsize of the tick labels is set by the labelsize parameter:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
font = {'size': 20}
ax.tick_params('z', labelsize=font['size'])
(To set the label size for all three axes you can use ax.tick_params(labelsize=20).)
Related
I want the picker event to simply display the legend label when I click on any of the points on my scatter plot. This is what I have and looks like:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# x y data and legend labels
x = np.random.uniform(0, 100, 50)
y = np.random.uniform(0, 100, 50)
ID = np.random.randint(0,25,50)
# define the event
def onpick(event):
ind = event.ind
print('x:', x[ind], 'y:', y[ind])
# create the plot
fig, ax = plt.subplots()
scatter = ax.scatter(x, y, c = ID, picker=True)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.legend(*scatter.legend_elements(num=list(np.unique(ID))),
loc="center left",
title='ID',
bbox_to_anchor=(1, 0.5),
ncol=2
)
ax.ticklabel_format(useOffset=False)
ax.tick_params(axis = 'x',labelrotation = 45)
plt.tight_layout()
# call the event
fig.canvas.mpl_connect('pick_event', onpick)
The scatter plot:
The current output on click:
I want it to print something like:
x: [76.25650514] y: [59.85198124] ID: 11 # the corresponding legend label
I have been searching through the web and couldn't find much I can duplicate from.
Generally, the way you would get the label of the point you clicked on would be print(event.artist.get_label()) but with your custom legends labels, the only thing that prints is _child0. However, due to your custom labels, you can use your variable ID just like how you are using your x and y variables e.g. print('id:', ID[ind]).
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# x y data and legend labels
x = np.random.uniform(0, 100, 50)
y = np.random.uniform(0, 100, 50)
ID = np.random.randint(0,25,50)
# define the event
def onpick(event):
ind = event.ind
print(event.artist.get_label()) # How you normally get the legend label
print('id:', ID[ind]) # How you can get your custom legend label
print('x:', x[ind], 'y:', y[ind])
# create the plot
fig, ax = plt.subplots()
scatter = ax.scatter(x, y, c = ID, picker=True)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.legend(*scatter.legend_elements(num=list(np.unique(ID))),
loc="center left",
title='ID',
bbox_to_anchor=(1, 0.5),
ncol=2
)
ax.ticklabel_format(useOffset=False)
ax.tick_params(axis = 'x',labelrotation = 45)
plt.tight_layout()
# call the event
fig.canvas.mpl_connect('pick_event', onpick)
plt.show()
Clicking on the yellow most point gives:
_child0
id: [24]
x: [84.73899472] y: [3.07532246]
Clicking on a very purple point gives:
_child0
id: [2]
x: [99.88397652] y: [98.89144833]
I am trying to align multiple subplots with a zoomed inset plot. Something like this:
|‾ ‾ ‾ ‾| |‾ ‾| |‾ ‾| |‾ ‾|
| | |_ _| |_ _| |_ _|
| |
|_ _ _ _|
I have tried using subplot2grid but I am not sure how to specify this kind of alignment. I am using a modified version of the Zoom region inset axes example in the matplotlib gallery: https://matplotlib.org/stable/gallery/subplots_axes_and_figures/zoom_inset_axes.html
Here is the reproducible example:
from matplotlib import cbook
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import numpy as np
def get_demo_image():
z = cbook.get_sample_data("axes_grid/bivariate_normal.npy", np_load=True)
# z is a numpy array of 15x15
return z, (-3, 4, -4, 3)
ax1 = plt.subplot2grid((2, 2), (0, 0), rowspan=2)
# make data
Z, extent = get_demo_image()
Z2 = np.zeros((150, 150))
ny, nx = Z.shape
Z2[30:30+ny, 30:30+nx] = Z
ax1.imshow(Z2, extent=extent, origin="lower")
# inset axes....
axins = ax1.inset_axes([1.1, 0.5, 0.5, 0.5])
axins.imshow(Z2, extent=extent, origin="lower")
# sub region of the original image
x1, x2, y1, y2 = -1.5, -0.9, -2.5, -1.9
axins.set_xlim(x1, x2)
axins.set_ylim(y1, y2)
axins.set_axis_off()
ax1.indicate_inset_zoom(axins, edgecolor="black")
ax2 = plt.subplot2grid((2, 2), (0, 1))
plt.tight_layout()
plt.show()
output:
I want ax2 to be aligned with axins - i.e. it should be the same size as the zoomed inset plot and placed side-by-side. How do I achieve this with matplotlib?
I've been able to achieve that, but I fear that it only works as long as you use an equal aspect ratio on the second axis (maybe you are plotting another image with height=width):
from matplotlib import cbook
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
import numpy as np
def get_demo_image():
z = cbook.get_sample_data("axes_grid/bivariate_normal.npy", np_load=True)
# z is a numpy array of 15x15
return z, (-3, 4, -4, 3)
gs = GridSpec(1, 2)
fig = plt.figure()
ax1 = fig.add_subplot(gs[0, 0])
ax2 = fig.add_subplot(gs[0, 1])
# make data
Z, extent = get_demo_image()
Z2 = np.zeros((150, 150))
ny, nx = Z.shape
Z2[30:30+ny, 30:30+nx] = Z
ax1.imshow(Z2, extent=extent, origin="lower")
# inset axes....
axins = ax1.inset_axes([1.1, 0.5, 0.5, 0.5])
axins.imshow(Z2, extent=extent, origin="lower")
# sub region of the original image
x1, x2, y1, y2 = -1.5, -0.9, -2.5, -1.9
axins.set_xlim(x1, x2)
axins.set_ylim(y1, y2)
axins.set_axis_off()
ax1.indicate_inset_zoom(axins, edgecolor="black")
ax2.set_aspect("equal")
plt.tight_layout()
plt.show()
Inspired by Davide_sd's answer it is possible to specify the following GridSpec, which seems to (almost) give my desired results in a hacky way:
gs = GridSpec(2, 4, hspace=-0.5)
fig = plt.figure()
ax1 = fig.add_subplot(gs[:2, :2])
ax2 = fig.add_subplot(gs[0, 3])
output:
I want to plot some data x and y in which I need the marker size to depend on a third array z. I could plot them separately (i.e., scatter x and y with size = z, and errorbar without marker, fmc = 'none') and this solves it. The problem is that I need the legend to show the errorbar AND the dot, together:
and not
Code is here with some made-up data:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(1,10,100)
y = 2*x
yerr = np.random(0.5,1.0,100)
z = np.random(1,10,100)
fig, ax = plt.subplots()
plt.scatter(x, y, s=z, facecolors='', edgecolors='red', label='Scatter')
ax.errorbar(x, y, yerr=yerr, xerr=0, fmt='none', mfc='o', color='red', capthick=1, label='Error bar')
plt.legend()
plt.show()
which produces the legend I want to avoid:
In errorbar the argumentmarkersizedoes not accept arrays asscatter` does.
The idea is usually to use a proxy to put into the legend. So while the errorbar in the plot may have no marker, the one in the legend has a marker set.
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(1,10,11)
y = 2*x
yerr = np.random.rand(11)*5
z = np.random.rand(11)*2+5
fig, ax = plt.subplots()
sc = ax.scatter(x, y, s=z**2, facecolors='', edgecolors='red')
errb = ax.errorbar(x, y, yerr=yerr, xerr=0, fmt='none',
color='red', capthick=1, label="errorbar")
proxy = ax.errorbar([], [], yerr=[], xerr=[], marker='o', mfc="none", mec="red",
color='red', capthick=1, label="errorbar")
ax.legend(handles=[proxy], labels=["errorbar"])
plt.show()
I created the following histogram from the frequeny of each class in a training set
The label of each class is too long and is similar to
Speed limit (20km/h)
Can I place each label on the bar itself?
Maybe something like this?
import numpy as np
import matplotlib.pyplot as plt
N=5
xlabel = ["Speed limit ("+str(i)+"km/h)" for i in range(0,N)]
xs = np.arange(0,7,1.5)
ys = [8,6,10,7,9]
width = 0.3*np.ones(N)
fig, ax = plt.subplots()
bars = ax.bar(xs, ys, width, color='k',alpha=0.3)
plt.xticks(xs, xlabel,rotation=270)
for i,bar in enumerate(bars):
height = bar.get_height()
ax.text(bar.get_x() + bar.get_width()/2., 0.1*height,
'%s' % xlabel[i],rotation=90,ha='center', va='bottom')
plt.show()
To change it to horizontal bar plot:
import numpy as np
import matplotlib.pyplot as plt
N = 5
xlabel = ["Speed limit ("+str(i)+"km/h)" for i in range(0,5)]
xs = np.arange(0,5)/2
ys = [8,6,10,7,9]
width = 0.3*np.ones(N)
fig, ax = plt.subplots()
bars = ax.barh(xs, ys, width, color='k',alpha=0.3)
plt.xticks([])
for i,bar in enumerate(bars):
height = bar.get_height()
ax.text(bar.get_x()+3, bar.get_y()+bar.get_height()/3,
'%s' % xlabel[i],rotation=0,ha='center', va='bottom')
plt.tight_layout()
plt.show()
I would like to define colors sections (blue: [0-15000], green: [15000-23000], red[23000,]) that should be used for y-values. Is it somehow possible in matplotlib?
You can color regions on a matplotlib plot using collections.BrokenBarHCollection:
import matplotlib.pyplot as plt
import matplotlib.collections as collections
fig = plt.figure()
ax = fig.add_subplot(111)
# Plot your own data here
x = range(0, 30000)
y = range(0, 30000)
ax.plot(x, y)
xrange = [(0, 30000)]
yrange1 = (0, 15000)
yrange2 = (15000, 23000)
yrange3 = (23000, 30000)
c1 = collections.BrokenBarHCollection(xrange, yrange1, facecolor='blue', alpha=0.5)
c2 = collections.BrokenBarHCollection(xrange, yrange2, facecolor='green', alpha=0.5)
c3 = collections.BrokenBarHCollection(xrange, yrange3, facecolor='red', alpha=0.5)
ax.add_collection(c1)
ax.add_collection(c2)
ax.add_collection(c3)
plt.show()