Search code examples
matplotliberrorbar

Errorbar variable marker size


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:

enter image description here

and not

enter image description here

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:

enter image description here

In errorbar the argumentmarkersizedoes not accept arrays asscatter` does.


Solution

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