I'm trying to generate a line plot of an xarray DataArray whose time coordinate is in cftime.DatetimeNoLeap. Matplotlib pyplot.plot returns an error message. This notebook used to work, but I've updated my environment (now using matplotlib v3.6.3, xarray v2023.1.0, cftime v1.6.2) and now it doesn't. Here is the cell that fails:
fig = plt.figure(figsize=(5,5))
ax1 = fig.add_subplot(2,1,1)
ax1.plot(obs_reg1sst.time,obs_reg1sst,color='k',marker='.',markersize=6,label='OBS')
The error message is: TypeError: float() argument must be a string or a real number, not 'cftime._cftime.DatetimeNoLeap'
I haven't found any relevant information after a google search, so any help would be much appreciated.
Here's a function that I've previously used to convert time values into a numpy array with units of year, which are usable in plotting functions:
def time_year_plus_frac(ds, time_name):
"""return time variable, as numpy array of year plus fraction of year values"""
# this is straightforward if time has units='days since 0000-01-01' and calendar='noleap'
# so convert specification of time to that representation
# get time values as an np.ndarray of cftime objects
if np.dtype(ds[time_name]) == np.dtype("O"):
tvals_cftime = ds[time_name].values
else:
tvals_cftime = cftime.num2date(
ds[time_name].values,
ds[time_name].attrs["units"],
ds[time_name].attrs["calendar"],
)
# convert cftime objects to representation mentioned above
tvals_days = cftime.date2num(
tvals_cftime, "days since 0000-01-01", calendar="noleap"
)
return tvals_days / 365.0
If you replace obs_reg1sst.time
with time_year_plus_frac(obs_reg1sst, "time")
, you might be in business (after importing cftime, and numpy as np). The function is written to work if ds.time has been converted to cftime objects or not.
Thanks Keith. Looks like this function will help me avoid the issue, but I'm left wondering why this cftime/matplotlib incompatibility comes and goes.
@Stephen Yeager have you ever tried using nc-time-axis? In the past it has helped me with cftime/matplotlib issues
@Katie Dagon Thanks very much for that suggestion! Plot works fine after importing nc-time-axis.
Deepak Cherian has marked this topic as resolved.
So, was nc-time-axis added to the NPL environment? Who should we contact to make this happen?
@David Bailey It looks like you can check packages in NPL using conda list --name npl-2023a
(after module load conda
).
I do see nc-time-axis version 1.4.1 listed under npl-2023a.
Thanks for this. However, this is still not working for me. I import nc_time_axis and it still gives me the error:
ValueError: The values must be numbers or instances of "nc_time_axis.CalendarDateTime" or "cftime.datetime".
From our netCDF files time is cftime.datetimeNoLeap. Is there another conversion I am missing?
Is this an error at the import step or later on?
Deepak Cherian has marked this topic as unresolved.
A full error message would be useful.
@Michael Levy helped me figure this out. I was trying to adjust the xticks manually and the syntax does not work with the cftime object. Once I removed the xticks statement, it works perfectly!
Last updated: May 16 2025 at 17:14 UTC