1

I have a barplot I am trying to plot without the x-axis ticks overlapping. I have settled on an angle of 45 degrees, and a max. number of ticks of 50, as this is about the max. of what can be shown without overlapping (IF the ticks are tilted at 45 degrees).

However, in my attempts I ran into the problem of Matplotlib not setting the x-axis to what I desire, whatever I try. I need to plot multiple datasets, for all of which the time runs from -15.8 through somewhere around 1200-1800.

I tried several solutions I found online, but all to no avail. The code below does not work, as it does not show the correct ticks. The range stops well before the last number in the timepoints list.

import numpy as np
from matplotlib import pyplot as plt

# Mock data
timepoints = list(np.arange(-15.8, 1276.2, 4))
patient_counts = np.random.randint(300, 600, len(timepoints))
x_tick_pos = [i + 0.5 for i in range(len(timepoints))]

# Plot barplot
fig, ax = plt.subplots(figsize=(16, 10))
ax.bar(x_tick_pos, patient_counts, align='center', width=1.0)

# Set x axis ticks
ax.set_xticklabels(timepoints, rotation=45)
ax.locator_params(axis='x', nbins=20)

plt.show()

enter image description here

Clearly, the x-axis does not come close to the expected values.

EDIT
To expand, this question is a follow-up from this thread. The code based on the answer in that question is as follows

# Plot barplot
fig, ax = plt.subplots(figsize=(16, 10))
ax.bar(x_tick_pos, patient_counts, align='center', width=1.0)

# Set x axis ticks
ax.set_xticks(x_tick_pos)
ax.set_xticklabels(x_ticks, rotation=45)

This appears to set the right x-ticks, except they overlap a lot- hence why I want only a max of 50 ticks to show:

enter image description here

Tim Stack
  • 3,209
  • 3
  • 18
  • 39
  • 3
    Getting rid of `ax.set_xticklabels(timepoints, rotation=45)` results in https://i.stack.imgur.com/beM78.png, which seems pretty legible. – BigBen Jan 21 '21 at 14:45
  • 2
    If you want more than 50 ticks and you don’t want to make the font size smaller then I guess you need to make the figure bigger? But do you really want more than 50 tick labels? – Jody Klymak Jan 21 '21 at 15:15
  • @BigBen thanks for your reply. The real data I use has X values that run from -15.8 through 1276.2. If I then do as you suggest, I end up with an x-axis that runs from 0 to 340, which naturally does not make much sense. I will try to edit my post to more accurately show the problem – Tim Stack Jan 22 '21 at 07:15

2 Answers2

0

This might be a simple case of fixing the x_tick_pos list expression. In your mock example, if we print them out ...

x_tick_pos = [i + 0.5 for i in range(len(timepoints))]
print(x_tick_pos[:5], x_tick_pos[-5:])

... we get what your figure reflects:

[0.5, 1.5, 2.5, 3.5, 4.5] [318.5, 319.5, 320.5, 321.5, 322.5]

Changing the assignment to

x_tick_pos = [i + 0.5 for i timepoints]

would appear to give the expected ticks.

Hans
  • 2,419
  • 2
  • 30
  • 37
  • Hi Hans, I just realised this and made an edit to my post to reflect why the tick positions are the way they are. Setting the positions to other values will result in other problems. – Tim Stack Jan 22 '21 at 08:15
0

The issue is that the positioning of the ticks is written so that they line up with another graph above this one, as per this post.

There are two solutions:

  1. forget about positioning the ticks relative to another graph, in case this bar plot is plotted in a standalone fashion
  2. resetting the ticks after plotting the bar plot to give them correct labels:
# Plot barplot
fig, ax = plt.subplots(figsize=(16, 10))
ax.bar(x_tick_pos, patient_counts, align='center', width=1.0)

# Set x axis ticks
ticks_step = int(len(missings_df.index) / 50)  # 50 here is the max. nr of ticks
x_ticks = [missings_df.index[i] for i in range(0, len(missings_df.index), int(len(missings_df)/50))]
x_tick_pos = [i + 0.5 for i in range(0, len(missings_df.index), int(len(missings_df)/50))]
ax.set_xticks(x_tick_pos)
ax.set_xticklabels(x_ticks, rotation=45)

This correctly plots the x-axis:

enter image description here

Tim Stack
  • 3,209
  • 3
  • 18
  • 39