Filipe
Filipe

Reputation: 659

Legend handle not correctly aligned in matplotlib

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: unaligned legend handle

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

Answers (1)

JohanC
JohanC

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()

legend with scatter dot superimposed on line

Upvotes: 1

Related Questions