import numpy as np
import matplotlib.pyplot as plt
# example data
x = np.arange(0.1, 4, 0.5)
y = np.exp(-x)
yerr = 0.1*np.random.rand(8)
fig, ax = plt.subplots()
ax.errorbar(x, y, linestyle='none', marker='*', yerr=yerr)
plt.show()
Hi, everyone! The goal is to add legend to the chart. y and yerr are labelled as 'mean' and 'std.Dev', respectively.
Related
I have to do three plots (contour, 3d surface, and heatmap) in matplotlib. The corresponding grid dimension for the three plots are ([0, 0], [0, 1], and [1, 0:1])
I have a few problems
The text annotation for heatmap (ax3), seem to fly out of ax3, into
ax1 and ax2. How can I constrain them to be within the ax3 only ?
Is this the fastest way to annotate text assuming that I do not want
to use seaborn ?
Can I get some tips on how to resolve my problems ?
Below is the code snippet to perform the plot operation
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gspec
from scipy.interpolate import griddata
import pyautogui
from scipy import stats
x = pyautogui.size()
width = x.width
height = x.height
x = np.arange(0, 10, 0.5)
y = np.arange(0, 10, 0.5)
X, Y = np.meshgrid(x, y)
data = 2 * (np.sin(X) + np.sin(3 * Y))
fig = plt.figure()
fig.set_figheight(height / 100)
fig.set_figwidth(width / 100)
fig.set_dpi(100)
gs = gspec.GridSpec(nrows=2, ncols=2)
ax1 = plt.subplot(gs[0, 0])
ax2 = plt.subplot(gs[0, 1], projection='3d')
ax3 = plt.subplot(gs[1, 0:1])
ctr = ax1.contourf(X, Y, data, 10, cmap='viridis')
ax1.clabel(ctr, inline=True, fontsize=8)
cbar = plt.colorbar(ctr, ax=ax1)
cbar.set_label('ColorbarLabel', size=15)
surf = ax2.plot_surface(X, Y, data, cmap='jet')
cbar1 = plt.colorbar(surf, ax=ax2)
cbar1.set_label('Colorbar2', size=15)
hmap = ax3.pcolormesh(X, Y, data, cmap='viridis')
cbar2 = plt.colorbar(hmap, ax=ax3)
for y in range(data.shape[0]):
for x in range(data.shape[1]):
ax3.text(x, y, '%.1f' % data[y, x], size=3)
I assume you want your heatmap to cover both columns. To achieve that you have to use ax3 = plt.subplot(gs[1, 0:2]): this tells matplotlib to use columns 0 and 1 (2 is excluded).
The text annotation for heatmap (ax3), seem to fly out of ax3, into ax1 and ax2. How can I constrain them to be within the ax3 only ?
That's because you are using the wrong coordinates in ax3.text.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gspec
from scipy.interpolate import griddata
import pyautogui
from scipy import stats
x = pyautogui.size()
width = x.width
height = x.height
x = np.arange(0, 10, 0.5)
y = np.arange(0, 10, 0.5)
X, Y = np.meshgrid(x, y)
data = 2 * (np.sin(X) + np.sin(3 * Y))
fig = plt.figure()
fig.set_figheight(height / 100)
fig.set_figwidth(width / 100)
fig.set_dpi(100)
gs = gspec.GridSpec(nrows=2, ncols=2)
ax1 = plt.subplot(gs[0, 0])
ax2 = plt.subplot(gs[0, 1], projection='3d')
ax3 = plt.subplot(gs[1, 0:2])
ctr = ax1.contourf(X, Y, data, 10, cmap='viridis')
ax1.clabel(ctr, inline=True, fontsize=8)
cbar = plt.colorbar(ctr, ax=ax1)
cbar.set_label('ColorbarLabel', size=15)
surf = ax2.plot_surface(X, Y, data, cmap='jet')
cbar1 = plt.colorbar(surf, ax=ax2)
cbar1.set_label('Colorbar2', size=15)
hmap = ax3.pcolormesh(X, Y, data, cmap='viridis')
cbar2 = plt.colorbar(hmap, ax=ax3)
for i in range(data.shape[0]):
for j in range(data.shape[1]):
ax3.text(x[j], y[i], '%.1f' % data[i, j], size=5)
I have a scatter plot on which I have colormapped the points using matplotlib.colors.LogNorm. This gives me the colour map scale which I desire, but I am not able to make this a discrete colormap.
Here's what I have:
I am aiming for something like this (ignoring the inset plot) :
I am able to use matplotlib.colors.BoundaryNorm with some level of success, but seem to lose the helpful formatting of the colorbar from matplotlib.colors.LogNorm:
Thanks
You can explicitly set the text for the colorbar ticks. Here is an example:
import matplotlib.pyplot as plt
from matplotlib.colors import BoundaryNorm, LogNorm
import numpy as np
x = np.linspace(0, 1, 60)
y = np.linspace(0, 1, 60)
c = np.logspace(-4, 1, 60)
fig, ax = plt.subplots()
sc1 = ax.scatter(x, y, c=c, cmap='viridis', norm=LogNorm())
cbar1 = plt.colorbar(sc1, ax=ax)
bounds = np.power(10.0, np.arange(-4, 2))
ncolors = len(bounds) - 1
cmap = plt.cm.get_cmap('turbo', ncolors)
norm = BoundaryNorm(boundaries=bounds, ncolors=ncolors)
sc2 = ax.scatter(x, y + 0 + 0.1, c=c, cmap=cmap, norm=norm)
cbar = plt.colorbar(sc2, ax=ax)
cbar.ax.set_yticklabels([f'$10^{{{np.log10(b):.0f}}}$' for b in bounds])
plt.show()
How can I reduce the distance between the numbering of an axis and the ticks corresponding to them. I tried using pad=0 for the tick_params but it doesn't seem to work. Below is a reproducible (simplified) code of my issue (and the figure):
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
plt.rcParams["figure.figsize"] = (10,10)
fig = plt.figure()
ax = Axes3D(fig)
ax.set_xlabel("X" , fontsize=20)
ax.set_ylabel("Y", fontsize=20)
ax.set_zlabel("Z" , fontsize=20)
ax.view_init(azim=-20)
ax.tick_params(axis='x', which='major', pad=0)
x = np.arange(0,10,0.01)
y = np.ones(len(x))
z = np.sin(x)
plt.plot(x,y,z)
Changing the values of pad seem to not have any effect. Note: I need the plot in that specific orientation (azim=-20). How can I achieve what I need? Thank you!
The pad argument also takes negative values to bring the ticklabels closer to the ticks.
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
fig = plt.figure()
ax = axes3d.Axes3D(fig)
ax.set_xlabel("X" , fontsize=20)
ax.set_ylabel("Y", fontsize=20)
ax.set_zlabel("Z" , fontsize=20)
ax.view_init(azim=-20)
ax.tick_params(axis='x', which='major', pad=-5)
x = np.arange(0, 10, 0.01)
y = np.ones(len(x))
z = np.sin(x)
plt.plot(x, y, z)
plt.show()
EDIT: Alternative outcome with set figure size and dpi value.
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
mpl.rcParams["figure.figsize"] = 10, 10
mpl.rcParams["figure.dpi"] = 100
fig = plt.figure()
ax = axes3d.Axes3D(fig)
ax.set_xlabel("X" , fontsize=20)
ax.set_ylabel("Y", fontsize=20)
ax.set_zlabel("Z" , fontsize=20)
ax.view_init(azim=-20)
ax.tick_params(axis='x', which='major', pad=-5)
x = np.arange(0, 10, 0.01)
y = np.ones(len(x))
z = np.sin(x)
plt.plot(x, y, z)
plt.show()
How can I move the z-axis of a 3D plot on the other side (including the label, ticks, and numbering). Here is small code and figure of what I mean:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
fig = plt.figure()
ax = Axes3D(fig)
ax.set_xlabel("X" , fontsize=20)
ax.set_ylabel("Y", fontsize=20)
ax.set_zlabel("Z" , fontsize=20)
x = np.arange(0,10,0.01)
y = np.ones(len(x))
z = np.sin(x)
plt.plot(x,y,z)
One possible solution:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
fig = plt.figure()
ax = Axes3D(fig)
tmp_planes = ax.zaxis._PLANES
ax.zaxis._PLANES = ( tmp_planes[2], tmp_planes[3],
tmp_planes[0], tmp_planes[1],
tmp_planes[4], tmp_planes[5])
ax.set_xlabel("X" , fontsize=20)
ax.set_ylabel("Y", fontsize=20)
# rotate label
ax.zaxis.set_rotate_label(False) # disable automatic rotation
ax.set_zlabel("Z axis label" , fontsize=20, rotation=90)
x = np.arange(0,10,0.01)
y = np.ones(len(x))
z = np.sin(x)
plt.plot(x,y,z)
I would like to ask how to produce a plot similar to that in the figure below? Basically, how to have x-axis at the top of the figure. Thanks
Image from: http://oceanographyclay1987.blogspot.com/2010/10/light-attenuation-in-ocean.html
Use
ax.xaxis.set_ticks_position("top")
For example,
import numpy as np
import matplotlib.pyplot as plt
numdata = 100
t = np.linspace(0, 100, numdata)
y = 1/t**(1/2.0)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.xaxis.set_ticks_position('top')
ax.yaxis.grid(linestyle = '-', color = 'gray')
ax.invert_yaxis()
ax.plot(t, y, 'g-', linewidth = 1.5)
plt.show()