时间序列处理由于气象上经常研究长期气候变化,这些数据动辄上十年,上百年的再分析数据也不少,如何提取这些时间序列,如何生成时间序列,便成为一个问题,之前看到摸鱼大佬作气候研究时使用xarray花式索引提取数据将我震的五体投地,于是也学习了一下时间序列的处理方法与经验。这里分为三部分,一是如何生成时间序列;二是使用xarray提取数据集里的时间序列;三是如何在绘图中使用定制化时间的显示方式。本章节是第一块的内容。
时间序列
作为一门以不间断观测,积累数据以进行研究的科学,长期保存的数据如何进行分析,这就牵扯到时间序列上了。以各气象观测站观测数据为例,常规六要素是每分钟采集一次,每小时报送一次整点报文,每天形成日数据,每月形成月报表,每年形成年报表。那么在这个过程中产生的时间序列就很恐怖了,时间序列的跨度也很大,从秒、时、日、月到年,处理时间序列成为一个不得不学习的内容。 这里还仅仅谈论观测数据,上面还有更多的再分析气候数据,动辄以十年为单位,这些数据也不好处理。 幸运的是,经过python多年发展,我们可以利用datetime、pandas、xarray甚至matplotlib方便快捷的处理时间序列,这些功能多种多样,而且互相之间多有联系,能掌握这项技能,搞科研可以事半功倍。 下面是简单介绍使用不同的库包进行时间序列的生成。
使用datetime生成时间序列
datetime库有三个最常使用的时间类,分别是date、time、datetime。
date是日期生成器,即年月日格式,常用参数有year、month、day。 time是时间生成器,即时分秒格式,常用参数有hour、minute、second。 datetime是日期时间生成器,即年月日时分秒格式,常用参数有year、month、day、hour、minute、second。 三种生成器是不一样的。即日期与时间不是一个类。date是可以含有年、月、日三个时间尺度,但是不含有时分秒;time同理,但datetime则既可以表示日期,又可以同时表示时间。 这里以date为例举出时间序列的生成。我们必须先生成首尾时间或其中的任意一个,才能进行时间序列的生成。我们可以使用关键字参数跟随的方式生成日期,例如:
date=pd.date_range(start='2023-01-01',periods=31,freq='D')date 也可以使用位置参数跟随的方式生成日期,这种方法简便些:
date=pd.date_range(end='2023-12',periods=12,freq='MS')date 然后,可以使用numpy.arange函数生成时间序列:
import pandas as pdimport numpy as npimport datetimeimport matplotlib.dates as mdatesstart=datetime.datetime(2023,1,1,8)end=datetime.datetime(2023,1,1,20)timedelta=datetime.timedelta(hours=1)datetime_array=mdates.drange(start,end,timedelta)datetime_array
这里可以修改步长,使生成的时间序列变化步长。与Python规则一致,生成的时间序列是左闭右开的,所以没有4月7日。但是这种方法有个问题,即仅能以天day为唯一划分步长单位,不能生成其他的时间步长。上面这个时间生成序列的1,其实是1D,即
这是因为date函数的year、month、day都是必须参数,所以生成的单位就是日。为了解决这个问题,我们可以引入numpy的时间处理模块,将时间单位统一。
上述程序的含义是生成的date1、date2的时间单位强制变换为月,这时时间单位就统一为月,可以生成逐月序列而非逐日序列,然后再强制变换为日单位。 为何会这么复杂,是因为datetime库没有时间序列生成器,一定要借助其他方式才能生成时间序列。 还有一种列表推导的方式生成时间序列,这是和鲸社区上ID名为啸不露齿写的,应该还是南信的校友,似乎更好理解一些。
表中进行了嵌套推导,给每一年推导12个月,然后推导2年,形成时间序列。最后还是需要使用pandas将时间列表转换为时间序列。 说到底,就是因为datetime自身没有携带简便的时间序列生成器,所以需要变来变去。但是为啥仍然要列出这一节?不难猜出——datetime其实是下面这些简便方法的基底。
使用numpy生成时间序列
从上面我们已经不难看出,比datetime更厉害的其实就是numpy,numpy的array自身带有一个type属性,合理使用type属性可以花式变换时间的单位格式。numpy还可以直接使用字符串生成时间序列,并指定type。比如:
通过给与不同的type,生成的数组格式也是不一样的,上面指定格式为日Day,若指定为月则
数组值变为与月单位对应,不再含有日单位,同样还可以加上小时单位
这里数组值变为带小时数据,type也对应变化。 这样,我们可以更加方便的生成时间序列。例如生成一个月的每日数据:
通过给与不同的dtype,可以方便的调整生成序列的步长,比如更换为以月为单位:
这里已经被收束到月单位,所以没有-01这个结尾,如果想要这个结尾,可以再变为D格式
从这个函数名字不难看出,这是numpy库给出的一个专门计算时间差值的函数。datetime也有类似的,但是他最大的时间单位为小时,np.timedelta64不同,他可以计算日、月、年等更大的时间差。举一个简单的例子,如何简单的将世界时变换为北京时,我们知道绝大数再分析资料都是以UTC存储的,但是BJC和UTC相差8个小时,这时便可以使用这个函数轻松换算。 UTC=
这样就在时间上变为北京时间了。 当然,与专门的程序员需要的精确时间相比还有一定差距,不过底线条件能用就行。
使用pandas生成时间序列
pandas是当年处理金融数据出名的,而金融数据时间性较强,所以pandas也有极强的时间序列处理能力。 pandas提供了一个内置函数pandas.date_range来生成时间序列。
是一个多格式时间序列生成器,专门用于生成时间,其常用关键字参数如下 start:开始时间,可以是时间字符串或者时间格式。 end:结束时间,可以是时间字符串或者时间格式。 periods:生成的时间序列长度,整数int。 freq:时间的单位。 start与end很好理解,即这个时间序列的开始时刻,这个开始时刻可以是字符串格式的时间,例如‘2021-01-01’,即代表开始时间为2023年1月1日。除开字符串外,还可以使用datetime生成的时间,例如 上述两种时间格式都可被接受。
periods,类似于np.arange(s,e,n)的这个n,用于确定时间序列的具体数量,若指定这个参数,则生成等分时间,例如
freq:时间序列差值的单位,但是start,end,periods,freq,不能四个同时使用,很好理解,比如上面这个序列,既指定开始又指定结束时间,还要生成固定数量时间,还要指定时间单位,这是不可能实现的,上述四个参数最多只能同时使用三个。 使用pd.date_range生成逐时数据 这里通过指定开始时间,结束时间,时间单位来生成一个时间序列:
使用pd.date_range生成逐日数据 这里通过指定开始时间,生成时间序列数量,时间单位来生成一个时间序列: