Reputation: 659
I'm plotting 3 things at once: a multicolored line via a LineCollection
(following this) and a scatter
(for the markers to "cover" where the lines are joining) for an average value, and a fill_between
for min/max. I get all the legend returns to plot a single legend handle. The graph looks like this:
As one can note, the circle marker is not aligned with the line. How can I adjust this?
The piece of the code that is plotting them and the legend looks like:
lc = LineCollection(segments, cmap='turbo',zorder=3)
p1 = ax.add_collection(lc)
p2 = ax.fill_between(x, errmin,errmax, color=colors[1],zorder=2)
ps = ax.scatter(x,y,marker='o',s=1,c=y,cmap='turbo',zorder=4)
ax.legend([(p2, p1, ps)], ["(min/avg/max)"],fontsize=tinyfont, facecolor='white', loc='lower right')
Upvotes: 1
Views: 452
Reputation: 80509
The legend has a parameter scatteryoffsets=
which defaults to [0.375, 0.5, 0.3125]
. As only one point is shown, setting it to [0.5]
should show the dot in the center of the legend marker.
To change the color of the line in the legend, one could create a copy of the existing line, change its color and create the legend with that copy.
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
import numpy as np
from copy import copy
x = np.arange(150)
y = np.random.randn(150).cumsum()
y -= y.min()
y /= y.max()
errmin = 0
errmax = 1
segments = np.array([x[:-1], y[:-1], x[1:], y[1:]]).T.reshape(-1, 2, 2)
fig, ax = plt.subplots(figsize=(12, 3))
lc = LineCollection(segments, cmap='turbo', zorder=3)
lc.set_array(y[:-1])
p1 = ax.add_collection(lc)
p2 = ax.fill_between(x, errmin, errmax, color='lightblue', zorder=2, alpha=0.4)
ps = ax.scatter(x, y, marker='o', s=5, color='black', zorder=4)
p1copy = copy(p1)
p1copy.set_color('crimson')
leg = ax.legend([(p2, p1copy, ps)], ["(min/avg/max)"], fontsize=10, facecolor='white', loc='lower right',
scatteryoffsets=[0.5])
ax.margins(x=0.02)
plt.show()
Upvotes: 1