Home > OS >  Matplotlib: space categorical x axis ticks by numerical value
Matplotlib: space categorical x axis ticks by numerical value

Time:02-11

I have data that I want to plot in a vertically-grouped scatter plot like this:

q = pd.DataFrame({'time': ['1', '1', '1'], 'velocity': [2, 3, 4]})
q2 = pd.DataFrame({'time': ['3', '3', '3'], 'velocity': [1, 2, 3]})
q3 = pd.DataFrame({'time': ['10', '10', '10'], 'velocity': [2, 1, 4]})

fig, ax = plt.subplots()
ax.scatter(q['time'], q['velocity'], c='green')
ax.scatter(q2['time'], q2['velocity'], c='blue')
ax.scatter(q3['time'], q3['velocity'], c='red')
ax.set_xticks([1, 3, 10])
ax.legend()

However, I want the categories on the x-axis to be spaced according to the name of the category. In this case, 'time' from data, data_2 and data_3 are, let's say, vectors populated with repeats of '1', '3', '10'.

I want the distance between category '1' and '3' to be 2 ticks, and the distance from '3' to '10' to be 7 ticks.

Tried to do:

ax.set_xticks(np.arange(0, 11, 1))
ax.set_xticklabels( [i if str(i) in ['1', '3', '10'] else 0 for i in range(11) ] )

But this only creates empty values and still sets the category positions to 0, 1, 2.

enter image description here

Do I need to re-structure my data to incorporate empty values in the interstitial categories, or is there another way?

CodePudding user response:

I think this is what you are trying to do:

scatter plot

In which case, the only thing you really need to do is change your time values from strings to numbers.

q = pd.DataFrame({'time': [1, 1, 1], 'velocity': [2, 3, 4]})
q2 = pd.DataFrame({'time': [3, 3, 3], 'velocity': [1, 2, 3]})
q3 = pd.DataFrame({'time': [10, 10, 10], 'velocity': [2, 1, 4]})

If you did that, and changed your xticklabels command to

ax.set_xticklabels( [i if i in [1, 3, 10] else 0 for i in range(11) ] )

then I think your image would come out the way you wanted.

Alternatively, if you want to keep your dataframe with string values, you can write a function that returns the values as numbers for plotting:

import pandas as pd
import matplotlib.pyplot as plt

def str2num(mylist):
    return([float(i) for i in mylist])

q = pd.DataFrame({'time': ['1', '1', '1'], 'velocity': [2, 3, 4]})
q2 = pd.DataFrame({'time': ['3', '3', '3'], 'velocity': [1, 2, 3]})
q3 = pd.DataFrame({'time': ['10', '10', '10'], 'velocity': [2, 1, 4]})

fig, ax = plt.subplots()

ax.scatter(str2num(q['time']), q['velocity'], c='green')
ax.scatter(str2num(q2['time']), q2['velocity'], c='blue')
ax.scatter(str2num(q3['time']), q3['velocity'], c='red')
ax.set_xticks(range(11))
ax.set_xticklabels( [i if i in [1, 3, 10] else 0 for i in range(11) ] )
  • Related