ThisCalculator

Everyday

Matplotlib Dates: Scatter Plots & Multiple Lines

Updated · Standard formula, shown below

Matplotlib Dates: Scatter Plots & Multiple Lines

Yes, Matplotlib handles dates perfectly for both scatter plots and multiple line plots, but you need to convert your date strings to datetime objects first. Once converted, you can plot them directly with plt.scatter() or plt.plot(), and Matplotlib will automatically format the axis with readable date labels.

Why Dates Need Special Handling

Matplotlib’s plotting functions expect numeric x-values. If you pass raw date strings like '2024-01-15', Matplotlib will either raise an error or plot them as categorical strings, which destroys the time spacing. The solution is to convert strings to datetime.datetime objects (or numpy.datetime64). Internally, Matplotlib converts these to a floating-point number representing days since 0001-01-01 UTC (for datetime) or days since 1970-01-01 (for numpy.datetime64). This numeric representation is what allows proper spacing, axis limits, and date tick formatting.

Setting Up Date Data

You have two common ways to get date objects:

  • Using datetime.strptime() for individual strings: datetime.strptime('2024-03-01', '%Y-%m-%d')
  • Using pandas.to_datetime() for a whole column: pd.to_datetime(df['date_column'])

For a list of strings, a list comprehension works well: dates = [datetime.strptime(d, '%Y-%m-%d') for d in date_strings]. Once you have a list of datetime objects, you can pass it directly as the x argument to plt.plot() or plt.scatter().

Scatter Plot with Dates

Here’s a minimal example:

import matplotlib.pyplot as plt
from datetime import datetime

dates = [datetime(2024, 1, 1), datetime(2024, 1, 15), datetime(2024, 2, 1)]
values = [10, 15, 7]

plt.scatter(dates, values)
plt.show()

This will produce a scatter plot where the x-axis shows dates like Jan 1, Jan 15, Feb 1. The spacing between points reflects the actual time difference (14 days vs 17 days). If you want to force a specific date range, use plt.xlim(datetime(2024,1,1), datetime(2024,2,15)).

Multiple Lines with Dates

Plotting multiple lines is just as straightforward. You call plt.plot() for each line on the same axes:

import matplotlib.pyplot as plt
from datetime import datetime

dates = [datetime(2024, 1, 1), datetime(2024, 1, 15), datetime(2024, 2, 1)]
series_a = [10, 15, 7]
series_b = [5, 12, 9]

plt.plot(dates, series_a, label='Product A')
plt.plot(dates, series_b, label='Product B')
plt.legend()
plt.show()

Both lines share the same date axis. If your two series have different date ranges, Matplotlib will still plot them correctly, automatically expanding the axis to cover all data points.

Controlling Date Tick Formatting

By default, Matplotlib chooses tick locations and formats automatically. For finer control, use matplotlib.dates:

  • DateLocator – sets tick positions (e.g., MonthLocator() for every month, DayLocator() for every day).
  • DateFormatter – sets the label format (e.g., DateFormatter('%Y-%m') for year-month).
import matplotlib.dates as mdates

plt.gca().xaxis.set_major_locator(mdates.MonthLocator())
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
plt.gcf().autofmt_xdate()  # rotates labels to avoid overlap

The autofmt_xdate() call is especially useful when you have many ticks.

Common Pitfalls and Solutions

  • String dates cause categorical plotting – Always convert to datetime before plotting.
  • Mixed timezones – If your data has timezone-aware datetimes, convert them all to UTC or your local timezone first (e.g., pd.to_datetime(df['col'], utc=True)).
  • Date axis limits – Use datetime objects in xlim(), not strings.
  • Overlapping labels – Call plt.gcf().autofmt_xdate() or rotate the labels manually.
  • Missing data gaps – If you have missing dates, Matplotlib will not connect lines across gaps unless you interpolate. For time series with gaps, consider using markevery or plotting only the available points.

Alternatives for Complex Time Series

If you need advanced date handling (resampling, timezone conversion, missing data interpolation), consider using Pandas for data manipulation and then plotting with Matplotlib. Pandas has built-in plotting methods that call Matplotlib under the hood, so you still get the same date formatting. For interactive plots with date zooming, you can use Plotly or Bokeh, but they require a different API.

Frequently Asked Questions

Why does my date plot show numbers instead of dates?

This happens when you pass numeric values (like timestamps or day counts) as x-data. Matplotlib only recognizes datetime objects or numpy.datetime64 arrays. Convert your numbers using pd.to_datetime(unit='s') if they are Unix timestamps, or datetime.fromordinal() if they are day counts.

How do I plot only the year on the x-axis?

Use a YearLocator() and DateFormatter('%Y'). For example: ax.xaxis.set_major_locator(mdates.YearLocator()) and ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y')).

Can I plot time of day (e.g., 14:30) on the x-axis?

Yes, if you have full datetimes, you can format the axis to show only the time using DateFormatter('%H:%M'). If you only have times without dates, you’ll need to create a dummy date (e.g., 2000-01-01) and add the time to it.

Why do my lines connect across missing dates?

Matplotlib connects consecutive data points regardless of the time gap. To avoid this, insert NaN values for missing dates or use a masked array. Alternatively, use plt.plot(..., markevery=...) to only show markers at actual data points.

How do I set the number of date ticks?

Use MaxNLocator with a DateLocator as the base, or simply set ax.xaxis.set_major_locator(mdates.DayLocator(interval=5)) to get a tick every 5 days. For a fixed number of ticks, you can use mdates.AutoDateLocator(minticks=5, maxticks=10).

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.