How to show only the first and last tick labels on the x-axis with subplots

Question:

To show only the first and last tick on x-axis, of both a line chart and bar chart side-by-side, produced by matplotlib and pandas.GroupBy, I have below lines.

However only the bar chart shows what’s wanted. The line chart has the latest month on the left upmost (it shall be on the right upmost), and missing the x tick on the right.

What went wrong and how can I correct it?

import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
from io import StringIO

csvfile = StringIO(
"""
Name;Year - Month;Score;Upvote
Mike;2023-01;884.22;5
Mike;2022-12;5472.81;36
Mike;2022-11;2017.59;15
Mike;2022-10;1845.23;14
Mike;2022-08;1984.32;15
Mike;2022-07;1033.33;8
Mike;2022-06;1587.64;24
Mike;2022-05;1019.93;20
Mike;2022-04;2359.3;45
Mike;2022-03;7478.72;140

""")

df = pd.read_csv(csvfile, sep = ';', engine='python')

for group_name, sub_frame in df.groupby("Name"):

    fig, axes = plt.subplots(nrows=1,ncols=2,figsize=(10,5))

    sub_frame_sorted = sub_frame.sort_values('Year - Month')       # sort the data-frame by a column

    sub_frame_sorted.plot(ax=axes[1], x="Year - Month", y="Score")
    sub_frame_sorted.plot(ax=axes[0], kind='bar', x="Year - Month", y="Upvote")

    axes[0].set_xticks([axes[0].get_xticks()[0], axes[0].get_xticks()[-1]])

    axes[1].set_xticks([axes[1].get_xticks()[0], axes[1].get_xticks()[-1]])

    plt.setp(axes[0].get_xticklabels(), rotation=0)
    plt.setp(axes[1].get_xticklabels(), rotation=0)

    plt.show()

enter image description here

Asked By: Mark K

||

Answers:

Since your x-axis is a string, the x ticks won’t be at position x, but at position 0..len(sub_frame_sorted)-1. For whatever reason (someone might come up with an explanation but it looks like a bug), if you debug axes[1].get_xticklabels() for Name Kate you’ll see:

[
 Text(-1.0, 0, '2022-07'),
 Text(0.0, 0, '2022-03'),
 Text(1.0, 0, '2022-04'),
 Text(2.0, 0, '2022-05'),
 Text(3.0, 0, '2022-06'),
 Text(4.0, 0, '2022-07'),
 Text(5.0, 0, '')
]

In order to avoid empty or wrong labels, you can provide the position directly since you know the data you’re plotting (sub_frame_sorted):

import matplotlib.pyplot as plt
import pandas as pd
from io import StringIO

csvfile = StringIO(
"""
Name;Year - Month;Score;Upvote
Mike;2022-09;192;5
Mike;2022-08;708;5
Mike;2022-07;140;3
Mike;2022-05;144;8
Mike;2022-04;60;10
Mike;2022-03;108;4
Kate;2022-07;19850;5
Kate;2022-06;19105;2
Kate;2022-05;23740;3
Kate;2022-04;19780;9
Kate;2022-03;15495;4 """)

df = pd.read_csv(csvfile, sep = ';', engine='python')

for group_name, sub_frame in df.groupby("Name"):

    fig, axes = plt.subplots(nrows=1,ncols=2,figsize=(10,5))

    sub_frame_sorted = sub_frame.sort_values('Year - Month')    # sort the data-frame by a column

    sub_frame_sorted.plot(ax=axes[0], kind='bar', x="Year - Month", y="Upvote")
    axes[1].plot(sub_frame_sorted["Year - Month"], sub_frame_sorted["Score"])

    axes[0].set_xticks([axes[0].get_xticks()[0], axes[0].get_xticks()[-1]])
    axes[1].set_xticks([0, len(sub_frame_sorted) - 1])

    plt.setp(axes[0].get_xticklabels(), rotation=0)
    plt.setp(axes[1].get_xticklabels(), rotation=0)

plt.show()

Edit: replacing pandas plot with matplotlib plot makes the ticks consistent again, so I would tend to say it’s a pandas bug.

Output:

enter image description here

Answered By: Tranbi
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.