Python | 绘制cftime时间轴
Python中处理时间的格式
Python中处理时间的格式非常多样。
Python标准库datetime模块:datetime.datetime:表示日期和时间。datetime.date:仅表示日期。datetime.time:仅表示时间。datetime.timedelta:表示两个日期或时间之间的差异。Python标准库time模块:以秒为单位的时间戳(自1970年1月1日以来)。numpy的datetime64:NumPy提供了datetime64数据类型,用于高效的日期时间数组操作。pandas的Timestamp:Pandas的Timestamp对象是datetime.datetime的扩展,提供了额外的时间戳功能和更好的性能。ISO 8601格式:国际标准组织定义的日期和时间表示方法,例如:2024-08-07T12:34:56+00:00。Unix时间戳:表示自1970年1月1日以来经过的秒数。cftime模块(用于气候和气象数据):专门用于处理气候模型和其他科学应用中的日期时间数据。这些格式和库可以处理从简单的日期和时间表示到复杂的时间序列分析的各种任务。在日常研究中,可以选择适合的库和格式来处理时间数据。
Netcdf数据中常用的时间格式
网络通用数据格式(英语:Network Common Data Form,netCDF)是一种自描述、与机器无关、基于阵列的科学数据格式,同时也是支持创建、访问和共享这一数据格式的函数库。该项目主页位于美国大气科学研究大学联盟(UCAR)的Unidata规划网站。它也是netCDF软件、标准开发、更新等的主要来源。netCDF格式是一种开放标准。
netCDF项目开始于1989年,UCAR目前对其积极支持,在新发行版中改进性能、增加功能并修正缺陷,当前版本系列是netCDF-4。netCDF的经典格式(CDF-1)和64位偏移量格式(CDF-2),是开放地理空间协会采用的国际标准。
NetCDF(nc)数据中的时间通常使用以下时间格式:
日数自参考日期(Days since)
这是NetCDF中最常见的时间单位格式。它表示从某个参考日期(通常是数据集的起始日期或某个标准日期)以来经过的天数。例如:days since 0001-01-01。
分钟数自参考日期(Minutes since)
以分钟为单位的时间表示。例如:hours since 0001-01-01。
分钟数自参考日期(Minutes since)
以分钟为单位的时间表示。例如:minutes since 0001-01-01。
秒数自参考日期(Seconds since)
这是最细粒度的时间单位格式,表示自参考日期以来的秒数。例如:seconds since 0001-01-01,类似于Unix时间戳。
混合时间单位
某些NetCDF文件可能包含混合时间单位,例如,以秒为单位的时间加上日数偏移量,格式如:hours since 1970-01-01 00:00:00 + seconds。
日历类型
NetCDF时间数据通常与特定的日历类型相关联,例如:
gregorian:公历。proleptic_gregorian:从公元1年开始的公历。noleap或365_day:每年365天,没有闰年。all_leap或366_day:每年366天,每个月31天。julian:朱利安日历。时间戳
某些NetCDF文件可能直接使用Unix时间戳,即自1970年1月1日以来的秒数。
ISO 8601格式
虽然不是NetCDF的内部表示,但NetCDF文件的元数据或属性可能包含ISO 8601格式的日期字符串。
相对时间
在某些应用中,NetCDF文件可能使用相对时间单位,如自某个特定事件以来的时间。
NetCDF文件的时间数据通常在文件的属性中详细说明,包括时间单位和日历类型。这些信息对于正确解析和理解数据集中的时间序列至关重要。在使用NetCDF数据时,应该检查这些属性以确保你正确地解释了时间数据。
Pandas库时间戳限制
现在回到今天的主题,气象中,经常使用pandas库的date_range来生成时间戳。
pd.date_range(start=1/1/2018, end=1/08/2018)
DatetimeIndex([2018-01-01, 2018-01-02, 2018-01-03, 2018-01-04,
2018-01-05, 2018-01-06, 2018-01-07, 2018-01-08],
dtype=datetime64[ns], freq=D)
然而使用这个方法来生成时间戳会有个限制:
Pandas库中的Timestamp类型通常基于64位整数来存储时间戳,这限制了它能够表示的日期范围。使用默认的Gregorian日历,Pandas能够处理的日期范围大约是从1677年9月21日到2262年4月11日。这个范围是由64位整数所能表示的最大和最小Unix时间戳决定的。
时间戳表示的限制取决于所选的分辨率。对于纳秒分辨率,可以使用 64 位整数表示的时间跨度限制为大约 584 年:
In [93]: pd.Timestamp.min
Out[93]: Timestamp(1677-09-21 00:12:43.145224193)
In [94]: pd.Timestamp.max
Out[94]: Timestamp(2262-04-11 23:47:16.854775807)
在matplotlib中绘制cftime时间轴
使用matplotlib可以绘制pandas.Timestamp时间轴
importrandom
import matplotlib.pyplot asplt
import pandas aspd
dt = pd.date_range(2017-02-01, 2017-03-01)
temperatures = [round(random.uniform(0, 12), 3) for _ inrange(len(dt))]
plt.figure(dpi = 300)
plt.plot(dt, temperatures)
plt.margins(0.1)
plt.ylim(0, 12)
plt.xticks(rotation = 45)
plt.xlabel("Date")
plt.ylabel("Temperature")
plt.show()
将时间换成cftime格式则会报错。
importrandom
import matplotlib.pyplot asplt
importcftime
calendar = "360_day"dt = [
cftime.datetime(year=2017, month=2, day=day, calendar=calendar)
for day in range(1, 31)
]
temperatures = [round(random.uniform(0, 12), 3) for _ inrange(len(dt))]
plt.figure(dpi = 300)
plt.plot(dt, temperatures)
plt.margins(0.1)
plt.ylim(0, 12)
plt.xticks(rotation = 45)
plt.xlabel("Date")
plt.ylabel("Temperature")
plt.show()
Out[1]:File ~\AppData\Roaming\Python\Python310\site-packages\matplotlib\cbook\__init__.py:1335 in_to_unmasked_float_array
return np.asarray(x, float)
TypeError: float() argument must be a string or a real number, not cftime._cftime.datetime解决方案
安装nc-time-axis库,使用conda安装:
conda install -c conda-forge nc-time-axis
或者pip安装:
pip install nc-time-axis
Example:importrandom
importcftime
import matplotlib.pyplot asplt
importnc_time_axis
calendar = "360_day"dt = [
cftime.datetime(year=2017, month=2, day=day, calendar=calendar)
for day in range(1, 31)
]
temperatures = [round(random.uniform(0, 12), 3) for _ inrange(len(dt))]
plt.figure(dpi = 300)
plt.plot(dt, temperatures)
plt.margins(0.1)
plt.ylim(0, 12)
plt.xlabel("Date")
plt.ylabel("Temperature")
plt.show()
导入nc-time-axis即可解决cftime时间轴的问题。
小编微信长按可关注