Tick labels on a pandas datetime axis are not aligned with the ticks

Question:

I’ve successfully created the code to generate a bunch of charts. However, the x axis labels are slightly offset (to the left) from the x axis tick marks.

Dataframe

  stationId       date variable  value  prefix uom
0    site 1 2016-04-07       pH   6.90     NaN  pH
1    site 1 2016-07-11       pH   6.80     NaN  pH
2    site 1 2017-10-09       pH   6.80     NaN  pH
3    site 1 2017-10-09       pH   6.80     NaN  pH
4    site 1 2016-06-29       pH   6.79     NaN  pH

There is nothing in the code which i can see why this should happen.

    #plot
for line,group in linedf.groupby(['variable']):
    x = group['date']
    ax1 = group.plot(x='date', figsize=(8.2,4.5),linestyle='--',
                     linewidth=0.75,rot=0,marker='o',markersize=3)
    
    #set axis labels and chart title
    plt.title("chartTitle", fontsize=12)
    ax1.set_xlabel('Date', fontsize=10)
    ax1.set_ylabel('GWL (mAHD)',fontsize=10)

    #set text font
    rcParams['font.family'] = 'serif'
    rcParams['font.serif'] = ['Cambria']

    #set dates for x tick labels
    years = mdates.YearLocator()   # every year
    months = mdates.MonthLocator()  # every month
    yearsFmt = mdates.DateFormatter('%Y')


    lgd = plt.legend(bbox_to_anchor=(0.0 ,-0.13, 1.0, -0.03), 
                     loc=2,ncol = 6, mode="expand", borderaxespad=0.0,shadow=True)
            
    plt.show()

x-axis not lining up with ticks

Full dataframe here

Selected columns below incase the link dies

stationId,date,variable,value
site 1,2016-07-04,pH,6.9
site 1,2016-11-07,pH,6.8
site 1,2017-09-10,pH,6.8
site 1,2016-06-29,pH,6.79
site 1,2016-03-14,pH,6.7
site 1,2016-07-25,pH,6.7
site 1,2016-04-20,pH,6.6
site 1,2016-08-08,pH,6.6
site 1,2018-06-08,pH,6.6
site 1,2018-08-20,pH,6.6
site 1,2018-11-26,pH,6.6
site 1,2018-10-12,pH,6.6
site 1,2016-05-16,pH,6.5
site 1,2016-06-14,pH,6.5
site 1,2016-08-24,pH,6.5
site 1,2016-05-09,pH,6.5
site 1,2016-09-20,pH,6.5
site 1,2016-11-14,pH,6.5
site 1,2016-12-14,pH,6.5
site 1,2017-05-01,pH,6.5
site 1,2017-01-18,pH,6.5
site 1,2017-12-04,pH,6.5
site 1,2017-06-19,pH,6.5
site 1,2017-03-07,pH,6.5
site 1,2017-08-14,pH,6.5
site 1,2017-09-15,pH,6.5
site 1,2017-09-25,pH,6.5
site 1,2017-11-12,pH,6.5
site 1,2018-04-16,pH,6.5
site 1,2018-05-14,pH,6.5
site 1,2018-05-28,pH,6.5
site 1,2018-06-13,pH,6.5
site 1,2018-09-07,pH,6.5
site 1,2018-05-09,pH,6.5
site 1,2018-09-17,pH,6.5
site 1,2018-03-10,pH,6.5
site 1,2018-10-31,pH,6.5
site 1,2018-12-11,pH,6.5
site 1,2016-12-01,pH,6.4
site 1,2016-05-31,pH,6.4
site 1,2016-04-10,pH,6.4
site 1,2016-10-17,pH,6.4
site 1,2017-01-31,pH,6.4
site 1,2017-02-16,pH,6.4
site 1,2017-02-03,pH,6.4
site 1,2017-03-15,pH,6.4
site 1,2017-03-29,pH,6.4
site 1,2017-08-05,pH,6.4
site 1,2017-05-22,pH,6.4
site 1,2017-07-19,pH,6.4
site 1,2017-02-08,pH,6.4
site 1,2017-08-29,pH,6.4
site 1,2017-11-13,pH,6.4
site 1,2018-01-22,pH,6.4
site 1,2018-05-02,pH,6.4
site 1,2018-02-19,pH,6.4
site 1,2018-03-19,pH,6.4
site 1,2018-06-25,pH,6.4
site 1,2016-02-18,pH,6.3
site 1,2016-02-03,pH,6.3
site 1,2016-05-05,pH,6.3
site 1,2016-03-02,pH,6.2
site 2,2016-06-29,pH,7.29
site 2,2017-02-08,pH,6.9
site 2,2017-09-15,pH,6.9
site 2,2016-05-31,pH,6.8
site 2,2017-02-16,pH,6.8
site 2,2017-09-25,pH,6.8
site 2,2017-09-10,pH,6.8
site 2,2016-06-14,pH,6.7
site 2,2016-08-24,pH,6.7
site 3,2018-09-07,pH,6.9
site 3,2018-08-20,pH,6.9
site 3,2018-07-23,pH,6.8
site 4,2016-06-29,pH,7.3
site 4,2016-07-25,pH,7.2
site 4,2016-11-07,pH,7.1
site 4,2017-09-15,pH,7.1
site 4,2016-06-14,pH,7.0
site 4,2017-08-14,pH,7.0
site 4,2017-09-25,pH,7.0
site 4,2018-06-04,pH,7.0
site 4,2018-09-07,pH,7.0
site 4,2018-10-31,pH,7.0
site 4,2018-10-12,pH,7.0
site 4,2016-05-16,pH,6.9
site 4,2017-05-01,pH,6.9
site 4,2017-12-04,pH,6.9
site 4,2017-05-22,pH,6.9
site 4,2017-06-19,pH,6.9
site 4,2017-03-07,pH,6.9
site 4,2017-02-08,pH,6.9
site 4,2017-08-29,pH,6.9
site 4,2017-11-12,pH,6.9
site 4,2018-02-01,pH,6.9
site 4,2018-04-30,pH,6.9
site 4,2018-05-28,pH,6.9
site 4,2018-06-13,pH,6.9
site 4,2018-06-08,pH,6.9
site 4,2018-03-10,pH,6.9
site 4,2018-12-11,pH,6.9
site 4,2018-11-26,pH,6.9
site 4,2016-04-20,pH,6.8
site 4,2016-08-08,pH,6.8
site 4,2016-08-24,pH,6.8
site 4,2016-10-17,pH,6.8
site 4,2016-04-11,pH,6.8
site 4,2016-11-14,pH,6.8
site 4,2017-01-31,pH,6.8
site 4,2017-02-16,pH,6.8
site 4,2017-02-03,pH,6.8
site 4,2017-03-29,pH,6.8
site 4,2017-08-05,pH,6.8
site 4,2017-05-06,pH,6.8
site 4,2017-07-19,pH,6.8
site 4,2017-09-10,pH,6.8
site 4,2017-10-31,pH,6.8
site 4,2017-11-13,pH,6.8
site 4,2017-11-27,pH,6.8
site 4,2018-01-22,pH,6.8
site 4,2018-02-19,pH,6.8
site 4,2018-05-03,pH,6.8
site 4,2018-04-16,pH,6.8
site 4,2018-05-14,pH,6.8
site 4,2018-06-25,pH,6.8
site 4,2018-07-23,pH,6.8
site 4,2018-08-20,pH,6.8
site 4,2018-09-17,pH,6.8
site 4,2018-10-15,pH,6.8
site 4,2016-12-01,pH,6.7
site 4,2016-02-18,pH,6.7
site 4,2016-02-03,pH,6.7
site 4,2016-03-14,pH,6.7
site 4,2016-07-04,pH,6.7
site 4,2016-05-31,pH,6.7
site 4,2016-05-09,pH,6.7
site 4,2016-09-20,pH,6.7
site 4,2016-04-10,pH,6.7
site 4,2016-12-14,pH,6.7
site 4,2017-01-18,pH,6.7
site 4,2018-05-02,pH,6.7
site 4,2018-03-19,pH,6.7
site 4,2018-05-09,pH,6.7
site 4,2016-03-02,pH,6.6
site 4,2016-05-05,pH,6.5
site 5,2016-02-03,pH,7.0
site 5,2017-01-31,pH,7.0
site 5,2017-02-16,pH,6.9
site 6,2016-06-29,pH,7.56
site 6,2016-08-08,pH,7.4
site 6,2018-02-01,pH,7.2
site 6,2018-06-08,pH,7.2
site 6,2018-03-10,pH,7.2
site 6,2018-10-15,pH,7.2
site 6,2016-05-09,pH,7.1
site 6,2016-04-11,pH,7.1
site 6,2017-12-04,pH,7.1
site 6,2017-03-07,pH,7.1
site 6,2017-02-08,pH,7.1
site 6,2017-09-15,pH,7.1
site 6,2017-11-12,pH,7.1
site 6,2018-05-28,pH,7.1
site 6,2018-09-07,pH,7.1
site 6,2018-07-23,pH,7.1
site 6,2016-04-20,pH,7.0
site 6,2017-05-06,pH,7.0
site 6,2017-06-19,pH,7.0
site 6,2017-07-19,pH,7.0
site 6,2017-08-14,pH,7.0
site 6,2017-08-29,pH,7.0
site 6,2017-09-25,pH,7.0
site 6,2017-10-31,pH,7.0
site 6,2017-11-13,pH,7.0
site 6,2017-11-27,pH,7.0
site 6,2018-01-22,pH,7.0
site 6,2018-02-19,pH,7.0
site 6,2018-06-04,pH,7.0
site 6,2018-10-31,pH,7.0
site 6,2018-11-26,pH,7.0
site 6,2018-10-12,pH,7.0
site 6,2017-05-22,pH,6.9
site 6,2017-09-10,pH,6.9
site 6,2018-05-02,pH,6.9
site 6,2018-05-03,pH,6.9
site 6,2018-03-19,pH,6.9
site 6,2018-04-16,pH,6.9
site 6,2018-04-30,pH,6.9
site 6,2018-05-14,pH,6.9
site 6,2018-06-13,pH,6.9
site 6,2018-06-25,pH,6.9
site 6,2018-08-20,pH,6.9
site 6,2018-05-09,pH,6.9
site 6,2018-09-17,pH,6.9
site 7,2016-06-29,pH,7.94
site 7,2016-04-20,pH,7.8
site 7,2016-05-16,pH,7.8
site 7,2016-11-07,pH,7.8
site 7,2016-05-09,pH,7.7
site 7,2016-12-01,pH,7.6
site 7,2016-03-02,pH,7.6
site 7,2016-05-05,pH,7.6
site 7,2016-07-25,pH,7.6
site 7,2016-08-24,pH,7.6
site 7,2016-04-10,pH,7.6
site 7,2016-10-17,pH,7.6
site 7,2017-02-03,pH,7.6
site 7,2017-02-16,pH,7.5
site 7,2017-03-15,pH,7.5
site 7,2018-08-20,pH,7.5
site 7,2016-02-18,pH,7.4
site 7,2016-07-04,pH,7.4
site 7,2016-05-31,pH,7.4
site 7,2016-06-14,pH,7.4
site 7,2016-09-20,pH,7.4
site 7,2016-04-11,pH,7.4
site 7,2017-01-18,pH,7.4
site 7,2017-01-31,pH,7.4
site 7,2017-11-12,pH,7.4
site 7,2018-03-19,pH,7.4
site 7,2018-05-28,pH,7.4
site 7,2018-06-25,pH,7.4
site 7,2018-06-08,pH,7.4
site 7,2018-05-09,pH,7.4
site 7,2018-12-11,pH,7.4
site 7,2018-11-26,pH,7.4
site 7,2018-10-12,pH,7.4
site 7,2016-08-08,pH,7.3
site 7,2016-12-14,pH,7.3
site 7,2017-05-01,pH,7.3
site 7,2017-02-08,pH,7.3
site 7,2017-09-15,pH,7.3
site 7,2017-09-25,pH,7.3
site 7,2017-11-27,pH,7.3
site 7,2018-06-13,pH,7.3
site 7,2018-09-07,pH,7.3
site 7,2018-10-15,pH,7.3
site 7,2018-10-31,pH,7.3
site 7,2016-02-03,pH,7.2
site 7,2016-11-14,pH,7.2
site 7,2017-03-07,pH,7.2
site 7,2017-08-14,pH,7.2
site 7,2017-08-29,pH,7.2
site 7,2017-10-31,pH,7.2
site 7,2017-11-13,pH,7.2
site 7,2018-02-01,pH,7.2
site 7,2018-02-19,pH,7.2
site 7,2018-07-23,pH,7.2
site 7,2018-09-17,pH,7.2
site 7,2018-03-10,pH,7.2
site 7,2017-12-04,pH,7.1
site 7,2018-05-03,pH,7.1
site 7,2017-05-22,pH,7.0
site 7,2017-05-06,pH,7.0
site 7,2017-08-05,pH,6.9
site 7,2017-06-19,pH,6.9
site 7,2016-03-14,pH,6.7
site 7,2017-09-10,pH,6.7
site 8,2016-11-07,pH,7.6
site 8,2018-05-28,pH,7.2
site 8,2016-03-02,pH,7.1
site 8,2017-05-01,pH,7.1
site 8,2017-08-05,pH,7.1
site 8,2016-04-20,pH,7.0
site 8,2017-01-18,pH,7.0
site 8,2017-01-31,pH,7.0
site 8,2017-02-03,pH,7.0
site 8,2017-09-10,pH,7.0
site 8,2018-06-04,pH,7.0
site 8,2018-06-13,pH,7.0
site 8,2018-09-07,pH,7.0
site 8,2018-12-11,pH,7.0
site 8,2016-05-16,pH,6.9
site 8,2018-02-19,pH,6.9
site 8,2018-03-10,pH,6.9
site 8,2016-12-01,pH,6.8
site 8,2016-02-18,pH,6.8
site 8,2016-10-17,pH,6.8
site 8,2017-06-19,pH,6.8
Asked By: TimW

||

Answers:

Without seeing the dataframe you are using (or at least a chunk of it) I have to speculate a bit, but it should suffice to simply adjust the alignment of the tick labels manually using

for tick in ax1.xaxis.get_major_ticks():
    tick.label1.set_horizontalalignment('center')

Without the dataframe I can’t test to ensure this works in your case, but from the plot in the question it appears the alignment of the x-tick labels has been set to 'right' and setting them to 'center' will align them how you desire.

    Drawn from the centered ticklabels example in the matplotlib docs.

Answered By: William Miller
  • This option is from a comment by ImportanceOfBeingErnest:
    • plt.setp(ax.get_xticklabels(), ha="center")
    • This occurs because pandas manipulates the tick parameters a bit.
  • Tested in python 3.11.3, pandas 2.0.1, matplotlib 3.7.1
import pandas as pd
import matplotlib.pyplot as plt

data = {'stationId': ['site1', 'site1', 'site1', 'site1', 'site1', 'site2', 'site2', 'site2', 'site2', 'site2'],
        'date': ['2016-04-07', '2016-07-11', '2017-10-09', '2017-10-12', '2016-06-29', '2016-04-07', '2016-07-11', '2017-10-09', '2017-10-12', '2016-06-29'],
        'variable': ['pH', 'pH', 'pH', 'pH', 'pH', 'pH', 'pH', 'pH', 'pH', 'pH'],
        'value': [6.9, 6.8, 6.8, 6.8, 6.79, 5.9, 5.8, 5.8, 5.8, 5.79]}
df = pd.DataFrame(data)

# convert to datetime; format= is not required, but it is faster if specified
df.date = pd.to_datetime(df.date, format='%Y-%m-%d')

# reshape the dataframe to plot each site
ph = df[df.variable.eq('pH')].pivot(index='date', columns='stationId', values='value')

# plot
ax = ph.plot(rot=0, figsize=(12, 5))

# center the labels
_ = plt.setp(ax.get_xticklabels(), ha="center")

enter image description here

Answered By: Trenton McKinney
  • The datetime xticks are right aligned because the 'date' column in the OP, and in the small sample in this answer, are datetime64[ns] Dtype.
    • set(tick.label1.get_horizontalalignment() for tick in ax.xaxis.get_major_ticks()) shows the allignment.
    • df.date[0] → Timestamp('2016-07-04 00:00:00')
    • This occurs with df.date = pd.to_datetime(df.date, format='%d/%m/%Y')
      • Specifying the format= option is irrelevant to this issue.
  • Since the data does not actually contain a time component, use df.date = pd.to_datetime(df.date, format='%d/%m/%Y').dt.date
    • df.date[0] → datetime.date(2016, 7, 4)
    • This change results in 'center' aligned xtick labels.
  • The datetime tick labels are formatted differently depending on the range in the data.
  • Tested in python 3.11.3, pandas 2.0.1, matplotlib 3.7.1
import pandas as pd

# using the csv data at the bottom of the OP
df = pd.read_csv('test.csv')

# convert the date column
df.date = pd.to_datetime(df.date, format='%Y-%m-%d').dt.date

# reshape the dataframe to plot each site
ph = df[df.variable.eq('pH')].pivot(index='date', columns='stationId', values='value')

# plot
ax = ph.plot(rot=0, figsize=(12, 5), linestyle='--', linewidth=0.75, marker='o', markersize=3)

# move the legend
_ = ax.legend(bbox_to_anchor=(1, 0.5), loc='center left', frameon=False)
  • Note the date xtick labels are center aligned without any additional formatting.

enter image description here

Answered By: Trenton McKinney