R71
R71

Reputation: 4523

sorting labels in matplotlib scaterplot

I have the following code for a scatterplot, and the corresponding plot is shown below:

x = ['C9-U2', 'C10-U5', 'C10-U5', 'C11-U1', 'C11-U1']
y = ['J',     'C',      'H',      'J',     'H']
plt.scatter(x,y)

enter image description here

In the plot, I would like to see both axes sorted, ie the x-axis should be [C9, C10, C11] (which is what it is, because I have entered the data in that sequence), and the y-axis should be [C, H, J] (which it is not).

How do I make sure that both axes are sorted?

Upvotes: 1

Views: 1840

Answers (3)

Dr. Duke
Dr. Duke

Reputation: 61

Following 'ImportanceOfBeingErnest ', the code could be shorten to

# initial plot to set sorted axis label
us = plt.plot(sorted(x),sorted(y))
[u.remove() for u in us]

# now plot the real thing, sorting not required
plt.scatter(x,y)

Upvotes: 0

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339220

This is actually a problem for which there is no good solution at the moment. The axis units are determined as they come from the input. So a solution is to predetermine the categorical order manually by plotting something in the correct order first and then remove it again.

import matplotlib.pyplot as plt

x = ['C9-U2', 'C10-U5', 'C10-U5', 'C11-U1', 'C11-U1']
y = ['J',     'C',      'H',      'J',     'H']

def unitsetter(xunits, yunits, ax=None, sort=True):
    ax = ax or plt.gca()
    if sort:
        xunits = sorted(xunits)
        yunits = sorted(yunits)
    us = plt.plot(xunits, [yunits[0]]*len(xunits),
                  [xunits[0]]*len(yunits), yunits)
    for u in us:
        u.remove()

unitsetter(x,y)
plt.scatter(x,y)

plt.show()

enter image description here

Here, sort is set to True, hence you get alphabetically sorted categories in both axes.

If you have a custom order you want the axis to obey, as is the case here (at least for the x axis) you would need to supply that order to the above function.

unitsetter(x, sorted(y), sort=False)
plt.scatter(x,y)

enter image description here

Upvotes: 3

Michael Bonnet
Michael Bonnet

Reputation: 240

I changed how your scatterplot is created quite a bit.

Here is my code:

import matplotlib.pyplot as plt

# This is your original code.
# x = ['C9-U2', 'C10-U5', 'C10-U5', 'C3-U1', 'C3-U1']
# y = ['J',     'C',      'H',      'J',     'H']
# plt.scatter(x,y)
# plt.show()

ordered_pairs = set([
     ('C9-U2', 'J'),
     ('C10-U5', 'C'),
     ('C10-U5', 'H'),
     ('C3-U1', 'J'),
     ('C3-U1', 'H')
])

x,y = zip(*ordered_pairs)
plt.scatter(x, y)
plt.show()

I turned your data points into a set of ordered pairs. This lets us zip the set, which is used to pack and unpack arrays with each argument passed. We use the * operator to inverse the process. You can read more about zip here.

When the code is ran, the image shown is the following, which I hope is what you were looking for:

result_of_shown_code

Upvotes: -1

Related Questions