2

I have a dataset plotted using plt.scatter(x,y) and an array of individual errors yerr and xerr that I want to put on each point as error bars using plt.errorbar(x,y,xerr,yerr, fmt='none').

As some values in xerr and yerr are positive, but some are negative I only want the error bar to go in the +ve or -ve direction according to this but when I use this code, it automatically plots in both directions.

How can I get it to just plot in a single, variable direction based on if the error array value is +ve or -ve?

I can think of a way to do it by creating new arrays to plot positive and negative directions but surely there's a quicker, easier way...

Fabio Mendes Soares
  • 1,357
  • 5
  • 20
  • 30
tomjboxer
  • 21
  • 1
  • Hello and welcome to SO! I encourage you to provide a [reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) so that we may help you find a solution that works for your particular problem. It should ideally contain a [small sample of data](https://stackoverflow.com/q/20109391/14148248) and some code showing what you have tried. It should be possible to copy-paste it and run it without any extra effort, as illustrated in the answers I have posted [here](https://stackoverflow.com/a/65579573/14148248) and [here](https://stackoverflow.com/a/66198319/14148248). – Patrick FitzGerald Feb 15 '21 at 13:52
  • 1
    Have you tried using `uplims` and `lolims` as shown in [this example](https://matplotlib.org/stable/gallery/statistics/errorbar_limits.html)? – Patrick FitzGerald Feb 15 '21 at 13:53

1 Answers1

0

When providing one array for the x-errors, they are interpreted as symmetrical errors. To have different error bars left and right, a tuple of two arrays can be given: one array with maximum(0, -xerr) and one with maximum(0, xerr). Note that these values are supposed to be positive. The y-errors work similarly.

import matplotlib.pyplot as plt
import numpy as np

x, y = np.random.uniform(1, 50, size=(2, 20))
xerr, yerr = np.random.uniform(-4, 4, size=(2, 20))
plt.errorbar(x, y,
             xerr=(np.maximum(0, -xerr), np.maximum(0, xerr)),
             yerr=(np.maximum(0, -yerr), np.maximum(0, yerr)),
             fmt='none', color='navy')
plt.show()

example plot

Here is an example with x and y on a grid:

x = np.tile(np.arange(10, 160, 10), 10)
y = np.repeat(np.arange(10, 110, 10), 15)
xerr, yerr = np.random.uniform(-4, 4, size=(2, len(x)))
plt.errorbar(x, y,
             xerr=(np.maximum(0, -xerr), np.maximum(0, xerr)),
             yerr=(np.maximum(0, -yerr), np.maximum(0, yerr)),
             fmt='none', color='navy')
plt.show()

x and y on grid

PS: The same plot can also be generated via short horizontal and vertical lines, calling plt.hlines() and plt.vlines():

plt.hlines(y, x, x+xerr, color='navy')
plt.vlines(x, y, y+yerr, color='navy')
JohanC
  • 71,591
  • 8
  • 33
  • 66