5

I'm trying to shade the marker of an errorbar plot, without shading the error bar lines.

Here's a MWE:

import matplotlib.pyplot as plt

x = [1, 2, 3, 4]
y = [1, 2, 3, 4]
dx = 0.1
dy = 0.1

plt.errorbar(x, y, xerr = dx, yerr = dy, marker = '.', 
             linestyle = ' ', color = 'black', capsize = 2,
             elinewidth = 0.5, capthick = 0.4, alpha = 0.8)

plt.savefig('MWE.pdf')
plt.show()

Also, how do I get rid of the marker edges without changing the capsize? If I put markeredgewidth = 0 the capsize gets reset.

Updated code:

import matplotlib.pyplot as plt
import matplotlib

x = [1, 2, 3, 4]
y = [1, 2, 3, 4]
dx = 0.1
dy = 0.1

other_marker_params = {'marker':'.',
                       'linestyle':' ',
                       'alpha':0.8,
                       'capthick':0.5,
                       'capsize':20,
                       'ecolor':'black',
                       'elinewidth':0.5}

(_, caps, _) = plt.errorbar(x, y, xerr=dx, yerr=dy, markerfacecolor = 'black',
                            markeredgewidth = 0, **other_marker_params)

for cap in caps:
    cap.set_markeredgewidth(1)
    cap.set_markersize(2)

plt.savefig('MWE.pdf')
plt.show()
Dmitriy Kisil
  • 2,858
  • 2
  • 16
  • 35
noibe
  • 327
  • 5
  • 18

1 Answers1

1

The second behaviour (markeredgewidth controlling capsize) is strange to me. My guess is because the marker and errorcap lines are both instances of a Line2D object they are both being passed the markeredgewidth parameter you set.

To answer your questions:

  • The colour of the marker can be controlled with the kwarg markerfacecolor as follows:

    plt.errorbar(x, y, xerr=dx, yerr=dy, 
                 markerfacecolor='red',
                 **other_marker_params) # a dict specifying kwargs in
    
  • The other issue can be addressed by manually editing the Line2D instances used for the caplines and error bar lines, these are returned by the plt.errorbar function:

    (_, caps, elines) = plt.errorbar(x, y, xerr=dx, yerr=dy, 
                                markerfacecolor='red', 
                                markeredgewidth=0,
                                **other_marker_params)
    
    for cap in caps:
        cap.set_markeredgewidth(1)
        cap.set_markersize(2)
        cap.set_alpha(1)
    for eline in elines:
        eline.set_alpha(1)
    

Using this I can get an image like this:

example_marker_control

Reference: I cannot take full credit for the second answer, it is amended from the accepted answer of this SO question.

Edit:

The dictionary other_marker_params may look something like:

other_marker_params = {'marker':'.', 
                       'linestyle':' ', 
                       'ecolor':'black', 
                       'elinewidth':0.5}
FChm
  • 2,515
  • 1
  • 17
  • 37
  • I don't know if I'm doing something wrong, but that didn't solve neither of my problems. I posted the updated code showing what I have right now. The error bar lines are still shaded due to the value of alpha (which I don't want, I only want the markers to be shaded while the lines should remain black), and `markeredgewidth` still resets `capsize`. – noibe Mar 31 '19 at 16:10
  • Hi I’ll have a look later to see if it all works. From memory it worked for me! One hacky solution is to plot the two separately, I.e, the error bars and the markers by calling plt.errorbar and plt.scatter – FChm Mar 31 '19 at 16:25
  • Hi, I've updated the answer: `markeredgewidth` still resets the `capsize` but then we reset it in our first for loop. To correct for the alpha we then set it once the error bars have been generated. – FChm Apr 01 '19 at 07:50