# Errorbar points with randomized z order

I have 3 different data vector with associated errors, and I’d like to plot each of them with a different color on the same ax, but randomizing the plot order of the points, so that the last data vector does not hide the two underlying ones.

So far, I have:

``````import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# ## generating pseudodata
x1 = np.logspace(-1, 2, 100)

X, Y = [], []
for i in range(3):
X.append(x1*(1 + 0.2*np.random.random((100,))))
Y.append(x1**2*(1 + 0.2*np.random.random((100,))))

fig, axarr = plt.subplots(1, 2, constrained_layout=True)

# only errorbars
ax = axarr[0]
for i, (x, y) in enumerate(zip(X, Y)):
ax.errorbar(x, y, xerr=0.3*x, yerr=0.3*y, fmt='.', label = str(i))
ax.set_xscale('log')
ax.set_yscale('log')
ax.legend()

# only scatter plot but randomized
ax = axarr[1]

X = np.concatenate(X)
Y = np.concatenate(Y)
plot_idx = np.random.permutation(X.size)
color_cycle = plt.rcParams['axes.prop_cycle'].by_key()['color']
colors = np.concatenate([np.repeat(color_cycle[i], 100) for i in range(3)])
labels = np.concatenate([np.repeat(str(i), 100) for i in range(3)])

sc = ax.scatter(X[plot_idx], Y[plot_idx], c=colors[plot_idx], s=10)

leg_elements = [plt.Line2D([0],[0],color=c, ls="",marker=".", label=str(i))
for i, c in enumerate(color_cycle[:3])]
ax.legend(handles=leg_elements)
ax.set_xscale('log')
ax.set_yscale('log')
``````

How can I mix up the two, as I can not pass a vector for the color argument of `ax.errorbar` ?
I was thinking about getting the points afterwards, and changing their zorder but I could not manage to do so

Unfortunately the way the `Artists` involved in `errorbar` are drawn as (mostly) atomic units per `ax.errorbar` call (and one color per call). On the other hand `scatter` is drawn as one unit for the whole data set, but can do color per point and you are seeing the intra-collection ordering.

I think the options are:

• use scatter and manually create the line collections for the error bars. However, I think that this will also produce some “Escher Effects” where the the markers will all be at one z and the lines will all be at one z so you could have odd layer effects.
• split the `errorbar` calls into N sets per color and cycle between them
• use the `alpha` channel to show the overlap

It might also be worth considering finding some other way to visualize this data that de-conflicts it (maybe vertical offsets? subplot?), but that is going to be very context/application dependent.

Is there anyway to change the zorder of `Artists` already drawn, for example after calling `ax.errorbar` ?

Otherwise I will split the `errorbar` calls into N sets per color and cycle between them as suggested.

1 Like

Every artist has a `set_zorder` method (matplotlib.artist.Artist.set_zorder — Matplotlib 3.6.2 documentation), however `errorbar` returns a Container of artist so you would have to do

``````ebar = ax.errorbar(....)
[art.set_zorder(-1) for art in ebar]
``````

and then re-render.