I'm attempting to plot categorical information against a series of datetime values in matplotlib. If the categorical data is represented as a string, I can get the plot to work. However, I want the Y-axis to be categorical so that it can be sorted in the correct order.
The following code segment shows what I have so far. In the plot, replace y with y_cat, and matplotlib throws an error:
import pandas as pd
import numpy as np
import calendar, datetime
import matplotlib as mpl
import matplotlib.pyplot as plt
# %matplotlib inline #for Jupyter notebooks
x = pd.date_range('2015/08/01', freq='4M', periods=9)
y = pd.Series(['Good', 'Very Good', 'Very Good', 'Average', 'Average', 'Good', 'Excellent', 'Excellent', 'Excellent'])
y_cat = pd.Categorical(y, categories=['Poor', 'Average', 'Good', 'Very Good', 'Excellent'], ordered=True)
fig, currAX = plt.subplots(figsize=(10, 4))
label_format = {'fontsize':12, 'fontweight':'bold'}
title_format = {'fontsize':15, 'fontweight':'bold'}
currAX.plot(x, y, color='crimson', linestyle='-')
#uncomment for error
#currAX.plot(x, y_cat, color='crimson', linestyle='-')
currAX.xaxis.set_major_formatter(mpl.dates.DateFormatter('%Y %b'))
currAX.spines['top'].set_visible(False)
currAX.spines['right'].set_visible(False)
currAX.spines['left'].set_visible(False)
currAX.set_xlabel('Review Period', **label_format)
currAX.set_ylabel('Review Rating', **label_format)
fig.tight_layout()
plt.show();
### ERROR:
IndexError: tuple index out of range
I'd like to see the graph with review categories in the Y-axis, sorted from best to worst, top to bottom
You're passing them as a list when it's expecting a tuple. Here the code corrected:
EDITED: if you also want to have ordered values on Y-axis you need to specify a number value in order for the plot to know where to place every point. Then replace the INT values with your labels. Here the updated code.
import pandas as pd
import numpy as np
import calendar, datetime
import matplotlib as mpl
import matplotlib.pyplot as plt
# %matplotlib inline #for Jupyter notebooks
x = pd.date_range('2015/08/01', freq='4M', periods=9).tolist()
y = pd.Series(['Good', 'Very Good', 'Very Good', 'Average', 'Average', 'Good', 'Excellent', 'Poor', 'Excellent']).tolist()
### create a conversion DICT
conversion = { \
"Poor" : 0, \
"Average" : 1, \
"Good" : 2, \
"Very Good" : 3, \
"Excellent" : 4 \
}
## open a list and insert in it the INT corresponding value
y_converted = []
for v in y :
y_converted.append(conversion[v])
fig, currAX = plt.subplots(figsize=(10, 4))
label_format = {'fontsize':12, 'fontweight':'bold'}
title_format = {'fontsize':15, 'fontweight':'bold'}
### pass as tuple
currAX.plot(x, y_converted, color='crimson', linestyle='-')
currAX.xaxis.set_major_formatter(mpl.dates.DateFormatter('%Y %b'))
currAX.spines['top'].set_visible(False)
currAX.spines['right'].set_visible(False)
currAX.spines['left'].set_visible(False)
currAX.set_xlabel('Review Period', **label_format)
currAX.set_ylabel('Review Rating', **label_format)
### tell matplotlib the ticks and labels to use on Y-axis
currAX.set_yticks( list(conversion.values()) )
currAX.set_yticklabels( list(conversion.keys()) )
fig.tight_layout()
plt.show();
Result:

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With