I am trying to iterate over multiple plots each with their own labels. The legend values are taken from the list 'iou'. The code below only generates 1 label for iou=0.2. Any help is appreciated.
iou=[0.2, 0.4, 0.6, 0.8]
from matplotlib import pyplot as plt
fig = plt.figure()
for i in range(0,4):
p=plt.plot(recall[i], precision[i], marker='+')
plt.legend(p, iou)
plt.title("PR curves")
plt.xlabel("Recall")
plt.ylabel("Precision")
In each iteration of your loop you'll want to use the label attribute of plt.plot and only after the loop call to plt.legend
from matplotlib import pyplot as plt
iou=[0.2, 0.4, 0.6, 0.8]
fig, ax = plt.subplots(1, 1)
for i in range(0,4):
ax.plot(recall[i], precision[i], marker='+', label=iou[i])
fig.legend()
ax.set_title("PR curves")
ax.set_xlabel("Recall")
ax.set_ylabel("Precision")
A minimal working example could be the following:
from matplotlib import pyplot as plt
import numpy as np
iou=[0.2, 0.4, 0.6, 0.8]
precision = np.random.randint(0, 10, size=(4, 10))
fig, ax = plt.subplots(1, 1)
for i in range(0,4):
ax.plot(np.r_[:10], iou[i] * precision[i], marker='+', label=iou[i])
fig.legend()
ax.set_title("PR curves")
ax.set_xlabel("Recall")
ax.set_ylabel("Precision")
Which gives the following:
Related
I'm trying to create some scatter plots, with seaborn with a specific area of each plot highlighted in red. However when I add the code for axvspan, it changes the x-axis. This is how the plots look prior to axvspan being applied.
When i apply the line for axvpsan:
fig, (ax0, ax1) = plt.subplots(2,1, figsize=(5,10))
ax0.axvspan("0.4", "0.8", color='red', alpha=0.3, label ='Problem Area')
sns.scatterplot(x='Values_1', y='Values_2', data=df3, color='green', ax=ax0)
sns.scatterplot(x='Values_3', y='Values_4', data=df3, color='green', ax=ax1)
plt.show()
It sends up looking like this:
Ultimately, the red section needs to only cover the data between 0.4 and 0.7, but by altering the x-axis it ends up covering all of it.
Any advice?
The unexpected behavior is resulting from passing the xmin and xmax arguments to matplotlib.pyplot.axvspan as str and not as float.
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd
# generate data
rng = np.random.default_rng(12)
df3 = pd.DataFrame({"Values_2": rng.random(100), "Values_1": np.linspace(0., 0.6, 100)})
fig, ax0 = plt.subplots(1,1, figsize=(6, 4))
ax0.axvspan(0.4, 0.8, color='red', alpha=0.3, label ='Problem Area')
sns.scatterplot(x='Values_1', y='Values_2', data=df3, color='green', ax=ax0)
plt.show()
This gives:
I have a plot with both a colorbar and a legend. I want to place the legend outside of the plot to the right of the colorbar. To accomplish this, I use bbox_to_anchor argument, but this causes the legend to get cut off:
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm
_, ax = plt.subplots()
extent = np.r_[0, 1, 0, 1]
space = np.linspace(0, 1)
probs = np.array([[norm.cdf(x + y) for x in space] for y in space])
colormap = ax.imshow(probs, aspect="auto", origin="lower", extent=extent, alpha=0.5)
colorbar = plt.colorbar(colormap, ax=ax)
colorbar.set_label(f"Probability")
ax.scatter(
[0.2, 0.4, 0.6], [0.8, 0.6, 0.4], color="r", label="Labeled Points",
)
plt.legend(loc="center left", bbox_to_anchor=(1.3, 0.5))
plt.title
plt.show()
Plot with legend cut off
To fix the legend, I insert a call to plt.tight_layout() before plt.show(), but this causes the aspect ratio to get distorted:
Plot with distorted aspect ratio
How can I show the entire legend and preserve the aspect ratio of the axes?
You can manage the ratio between axis height and width with matplotlib.axes.Axes.set_aspect. Since you want them to be equal:
ax.set_aspect(1)
Then you can use matplotlib.pyplot.tight_layout to fit the legend within the figure.
If you want to adjust margins too, you can use matplotlib.pyplot.subplots_adjust.
Complete Code
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm
_, ax = plt.subplots()
extent = np.r_[0, 1, 0, 1]
space = np.linspace(0, 1)
probs = np.array([[norm.cdf(x + y) for x in space] for y in space])
colormap = ax.imshow(probs, aspect="auto", origin="lower", extent=extent, alpha=0.5)
colorbar = plt.colorbar(colormap, ax=ax)
colorbar.set_label(f"Probability")
ax.scatter([0.2, 0.4, 0.6], [0.8, 0.6, 0.4], color="r", label="Labeled Points",)
plt.legend(loc="center left", bbox_to_anchor=(1.3, 0.5))
ax.set_aspect(1)
plt.tight_layout()
plt.subplots_adjust(left = 0.1)
plt.show()
I have two 2D arrays and I want to use to produce an image similar to the one that fallows, just with different limits on the axis.
Here is my attempt so far:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_xlim(-2.01, 2.01)
ax.set_ylim(-2.01, 2.01)
ax.set_zlim(-2.01, 2.01)
cmap = plt.cm.gray
im = ax.imshow(np.asarray(array1), cmap=cmap)
im.remove()
fig.colorbar(im)
plt.show()
The arrays I have, (array1 and array2) are two dimensional with sizes n by n. Any help or a point in the right direction will be greatly appreciated!
With help of Matplotlib - Plot a plane and points in 3D simultaneously, I am able to achieve this:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.set_zlim(0, 1)
ax.set_xticks([0, 0.2, 0.4, 0.6, 0.8, 1])
ax.set_yticks([0, 0.5, 1])
ax.set_zticks([0, 0.2, 0.4, 0.6, 0.8, 1])
cmap = plt.cm.gray
#plot vertical surface
y = 0.5
xx, zz = np.meshgrid(np.linspace(0,1,10), np.linspace(0,1,10))
p = ax.plot_surface(xx, y, zz, cmap=cmap, alpha=0.5)
x = 0.2
yy, zz = np.meshgrid(np.linspace(0,1,10), np.linspace(0,1,10))
p = ax.plot_surface(x, yy, zz, cmap=cmap, alpha=0.5)
fig.colorbar(p)
plt.show()
Note that I didn't use normal or dot just as another question do, because here you want to plot vertical planes.
Here's what I got(I'm working on the right occlusion):
I have tried the following to produce a regular polygon:
import matplotlib.pyplot as plt
import matplotlib.patches as patches
fig2 = plt.figure()
ax2 = fig2.add_subplot(111, aspect='equal')
ax2.add_patch(
patches.RegularPolygon(
(0.5, 0.5),
3,
0.2,
fill=False # remove background
)
)
fig2.savefig('reg-polygon.png', dpi=90, bbox_inches='tight')
plt.show()
While this produces a triangle, I haven't found any way to produce a trapezoid and and a parallelogram.
Are there any commands to do this? Or can I transform the regular polygon into one of the other shapes?
You would need to use a matplotlib.patches.Polygon and define the corners yourself.
import matplotlib.pyplot as plt
import matplotlib.patches as patches
fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal')
# Parallelogram
x = [0.3,0.6,.7,.4]
y = [0.4,0.4,0.6,0.6]
ax.add_patch(patches.Polygon(xy=list(zip(x,y)), fill=False))
# Trapez
x = [0.3,0.6,.5,.4]
y = [0.7,0.7,0.9,0.9]
ax.add_patch(patches.Polygon(xy=list(zip(x,y)), fill=False))
plt.show()
For filled patches with size greater than 1 x 1
fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal')
ax.set_xlim(0, 3)
ax.set_ylim(0, 3)
x = [0, 1.16, 2.74, 2, 0]
y = [0, 2.8, 2.8, 0, 0]
ax.add_patch(patches.Polygon(xy=list(zip(x,y)), fill=True))
x = [0.3,0.6,.5,.4]
y = [0.7,0.7,0.9,0.9]
ax.add_patch(patches.Polygon(xy=list(zip(x,y)), fill=True, color='magenta'))
One simple way to do it is creating a list of lists as the end points of the polygon( parallelogram/trapezoid) and plotting(or rather tracing) them.
import matplotlib.pyplot as plt
import matplotlib.patches as patches
fig2 = plt.figure()
ax2 = fig2.add_subplot(111, aspect='equal')
points = [[0.2, 0.4], [0.4, 0.8], [0.8, 0.8], [0.6, 0.4], [0.2,0.4]] #the points to trace the edges.
polygon= plt.Polygon(points, fill=None, edgecolor='r')
ax2.add_patch(polygon)
fig2.savefig('reg-polygon.png', dpi=90, bbox_inches='tight')
plt.show()
Also, note that you should use Polygon instead of RegularPolygon.
I am learning how to use subplots. For example:
import numpy
import matplotlib.pyplot as plt
plt.figure(1)
plt.subplot(221)
plt.subplot(222)
plt.subplot(223)
plt.show()
plt.close(1)
I am getting 3 subplots in figure1
Now I want to make a large subplot with the other subplots within the first one. I tried:
plt.figure(1)
plt.subplot(111)
plt.subplot(222)
plt.subplot(223)
But the first subplot disappears.
My question: is it possible to overlap subplots?
thank you
If you want a total control of the subplots size and position, use Matplotlib add_axes method instead.
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(6, 4))
ax1 = fig.add_axes([0.1, 0.1, 0.85, 0.85])
ax2 = fig.add_axes([0.4, 0.6, 0.45, 0.3])
ax3 = fig.add_axes([0.6, 0.2, 0.2, 0.65])
ax1.text(0.01, 0.95, "ax1", size=12)
ax2.text(0.05, 0.8, "ax2", size=12)
ax3.text(0.05, 0.9, "ax3", size=12)
plt.show()
You can use mpl_toolkits.axes_grid1.inset_locator.inset_axes to create an inset axes on an existing figure.
I added a print statement at the end which shows a list of two axes.
import matplotlib.pyplot as plt
import mpl_toolkits.axes_grid1.inset_locator as mpl_il
plt.plot()
ax2 = mpl_il.inset_axes(plt.gca(), width='60%', height='40%', loc=6)
ax2.plot()
print(plt.gcf().get_axes())
plt.show()
It's not possible to use plt.subplots() to create overlapping subplots. Also, plt.subplot2grid will not work.
However, you can create them using the figure.add_subplot() method.
import matplotlib.pyplot as plt
fig = plt.figure(1)
fig.add_subplot(111)
fig.add_subplot(222)
fig.add_subplot(223)
plt.show()