2

TLDR: I can use Axes.hlines(y, x1, x2) to plot horizontal lines on numerical axes, how do I do it on categorical axes?

My goal is to create horizontal lines, centered on category (string) values (e.g. 'a', ...) and extending 50% of the width between the categories on either side.


More detail

Consider the following 2 pandas.Series:

import pandas as pd
s1 = pd.Series([2, 2.5, -1, 3], pd.Index([6, 8, 10, 12], name='left-x')) # number index
s2 = pd.Series([2, 2.5, -1, 3], pd.Index(list('abcd'), name='x-value')) # str index

I can plot both as a bar graph with Axes.bar(x, y, width):

import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 2)
ax[0].bar(s1.index + 0.1, s1.values, width=1.8, align='edge') # width as numeric value
ax[1].bar(s2.index, s2.values, width=0.9) # width as fraction of distance between categories

enter image description here

But I cannot plot s2 as a hline graph with Axes.hlines(y, x1, x2)

import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 2)
ax[0].hlines(s1.values, s1.index, s1.index + 2)
ax[1].hlines(s2.values, ...) #<-- problem. s2.index is not numeric. What to do?

enter image description here

My goal is to create horizontal lines, centered on the index values ('a', ...) and extending 50% of the width between the categories on either side.

ElRudi
  • 2,122
  • 2
  • 18
  • 33
  • 1
    Internally, the categorical axis is represented as `0, 1, 2, 3`. So e.g. `1-0.5` to `1+0.5` is centered around `b`. – JohanC Sep 01 '21 at 18:49
  • This [answer](https://stackoverflow.com/a/59040003/7758804) in the duplicate. – Trenton McKinney Sep 01 '21 at 18:51
  • Many thanks @JohanC, that cleared things up! – ElRudi Sep 01 '21 at 18:59
  • I had actually seen that question you are linking to, @TrentonMcKinney. It does not use categorical data, but rather numerical data, for which I had already found a solution. My question is therefore not a duplicate. – ElRudi Sep 01 '21 at 18:59
  • 2
    Doesn't matter if the data is categorical: _Note that barplots are 0 indexed, regardless of the axis labels, so select xmin and xmax based on the bar index, not the tick label._ as also stated by @JohanC – Trenton McKinney Sep 01 '21 at 19:01
  • 2
    `ax[1].get_xticklabels()`: `[Text(0, 0, 'a'), Text(1, 0, 'b'), Text(2, 0, 'c'), Text(3, 0, 'd')]` and `ax[0].get_xticklabels()`: `[Text(4.0, 0, '4'), Text(6.0, 0, '6'), Text(8.0, 0, '8'), Text(10.0, 0, '10'), Text(12.0, 0, '12'), Text(14.0, 0, '14'), Text(16.0, 0, '16')]`. As you can see, the locations in your mre are integers, as stated in the duplicate. – Trenton McKinney Sep 01 '21 at 19:03
  • 1
    I'm sorry, I thought two questions are duplicates if they ask the same question. The linked question only mentions a numerical axis type, not a categorical axis, which is the whole point of my question and explicitly included in its title. I wasn't aware that question B is considered a duplicate of question A if a subsection of one of the (not-accepted) answers to A happens to mention something that gives a hint as to what the answer to B might be.              Anyways thanks again @JohanC for pointing me in the right direction and giving me useful information that answered my question! – ElRudi Sep 01 '21 at 19:25
  • 2
    Questions that are "permutations" or "slightly differentiated" are often closed as duplicates to other questions that are considered canonical, especially if an existing answer covers the new question. – Trenton McKinney Sep 01 '21 at 19:30

0 Answers0