I would like to set individual properties (zorder
and label
for example) for a specific element of a matplotlib.collections.PathCollection
. I couldn't find a way in the documentation.
Here I jot down a user case.
Let say we have the following snippet, and we'd like to change the zorder
of the red ball, bringing it to the top, by using the balls
handle, which is a matplotlib.collections.PathCollection
.
balls = plt.scatter([-1, 1], [0, 0], c = ['r', 'b'], s = 4e4)
plt.axis([-5, 5, -5, 5])
Does anyone have any idea about how to tweak individual paths of a PathCollection
?
The alternative would be using plt.plot('o')
, which actually returns a list
of handles. Unfortunately the plt.plot('o')
solution won't allow me to set a different colour per ball, since they would all belong to the same chart. So a for
loop would be required.
The drastic solution, which I bet I'll go for, since my deadline, is going of Inkscape :/
Not sure if this is the best solution, but it might help you.
From what I can see, the paths
in the PathCollection
are always plotted in the order they are created. So in your case, the path
with the x-position of -1
is created first, then the one with 1
.
You can switch that order after initially plotting them, by changing the offsets
, in your case using balls.set_offsets()
:
In [4]: balls = plt.scatter([-1, 1], [0, 0], c = ['r', 'b'], s = 4e4)
In [5]: plt.axis([-5, 5, -5, 5])
This creates the following figure:
In [42]: print balls.get_offsets()
[[-1. 0.]
[ 1. 0.]]
On [43]: balls.set_offsets([[1,0],[-1,0]])
Now, this has plotted the left-hand ball on top of the right-hand ball:
But as you can see, this has also switched the facecolors
around (since we set the order of that in the call to plt.scatter
as ['r','b']
. There's a solution to this, which is to also switch the facecolors
around:
In [46]: balls.set_facecolors(['b','r'])
Great, so putting that all together, we can define a function to switch the offsets and facecolors of any two arbitrary paths
in the PathCollection
.
import matplotlib.pyplot as plt
fig,ax = plt.subplots()
balls = ax.scatter([-3, -1, 1, 3], [0, 0, 0, 0], c = ['r', 'b', 'g', 'm'], s = 4e4)
ax.set_xlim(-6,6)
ax.set_ylim(-6,6)
plt.savefig('balls_01.png')
def switch_scatter(pathcoll,a,b):
# Switch offsets
offsets = pathcoll.get_offsets()[:]
offsets[[a,b]] = offsets[[b,a]]
# Switch facecolors
facecolors = pathcoll.get_facecolors()
facecolors[[a,b]] = facecolors[[b,a]]
# Switch sizes
sizes = pathcoll.get_sizes()
sizes[[a,b]] = sizes[[b,a]]
# Set the new offsets, facecolors and sizes on the PathCollection
pathcoll.set_offsets(offsets)
pathcoll.set_facecolors(facecolors)
pathcoll.set_sizes(sizes)
switch_scatter(balls,2,1)
plt.savefig('balls_02.png')
Heres balls_01.png
:
And here is balls_02.png
(where we switch ball 1 and ball 2 (the blue and green balls)
A final note: if you have other properties varying in your scatter plot (e.g. linecolor), you will also need to switch them around in the function I defined above.