周期是数据中出现重复模式所需的时间长度。更具体地说,它是模式的一个完整周期的持续时间。在这篇文章中,将介绍计算时间序列周期的三种不同方法。我们使用渥太华市数据集,主要关注每天的服务电话数量。因此不需要对病区名称进行初始数据处理。渥太华数据集可在渥太华市提供的数据门户网站上免费获得。让我们从2019-2022加载这些数据并将它们连接起来以获得df。fromgoogle.colabimportdrivedrive.mount('/content/gdrive')importpandasaspdimportmatplotlib.pyplotaspltimportseabornassnsimportnumpyasnpfile_path='/content/gdrive/MyDrive/ColabNotebooks/Data/SR-2019.xlsx'records2019=pd.read_excel(file_path)#,encoding='utf16')file_path='/content/gdrive/MyDrive/ColabNotebooks/Data/SR-2020.xlsx'records2020=pd.read_excel(file_path)#,encoding='utf16')file_path='/content/gdrive/MyDrive/ColabNotebooks/Data/2021_Monthly_Service_Requests_EN.xlsx'records2021=pd.read_excel(file_path)#,encoding='utf16')file_path='/content/gdrive/MyDrive/ColabNotebooks/Data/2022_Monthly_Service_Requests.csv'records2022=pd.read_csv(file_path)records=pd.concat([records2019,records2020,records2021,records2022],axis=0)让我们根据服务日期聚合此数据并获得一个简单的图表。记录["DATE_RAISED"]=pd.to_datetime(records.DATE_RAISED)record_by_date=records.groupby("DATE_RAISED")["TYPE"].count().sort_index()record_by_date.plot(figsize=(25,10))plt.ylabel('请求数')plt.grid(visible=True,which='both')plt.figure()record_by_date.iloc[100:130].??plot(figsize=(25,10))plt.ylabel('Numberofrequests')plt.grid(visible=True,which='both')fillmissing让我们检查一下我们的数据是否包含所有日期。start_date=record_by_date.index.min()end_date=record_by_date.index.max()#为感兴趣的时间段创建一个完整的日期范围date_range=pd.date_range(start=start_date,end=end_date,freq='D')#将日期范围与时间序列的索引进行比较missing_dates=date_range[~date_range.isin(record_by_date.index)]iflen(missing_dates)>0:print("Missingdates:",missing_dates)else:print("Nomissingdates")正如预期的那样,数据缺少一些日期值。让我们用相邻日期的平均值填充这些值。#重建索引以填充缺失的日期idx=pd.date_range(start=record_by_date.index.min(),end=record_by_date.index.max(),freq='D')record_by_date=record_by_date.reindex(idx,fill_value=0)#添加缺失日期及其周边值的平均值fordateinmissing_dates:prev_date=date-pd.DateOffset(days=1)next_date=date+pd.DateOffset(days=1)prev_val=record_by_date.loc[prev_date]ifprev_dateinrecord_by_date.indexelsenp.nannext_val=record_by_date.loc[next_date]ifnext_dateinrecord_by_date.indexelsenp.nanavg_val=np.nanmean([prev_val,next_val])record_by_date.loc[date]=avg_val这就是我们做所有的预处理,经过所有这些步骤,我们尝试检测这个时间序列的周期。一般来说,根据假期模式和一般人类习惯,我们希望在数据中看到7天的周期,所以让我们看看是否是这样。1、目视检查最简单的方法是目视检查。这是一种主观的方法,不是正式的或统计的方法,所以我把它作为我们列表中的原始方法。如果我们查看此图的放大部分,我们可以看到一个7天的周期。最低值出现在5月14日、21日和28日。但最高点似乎并不遵循这种模式。但是在更大的尺度上,我们仍然可以说这个数据集的周期是7天。我们来正式分析一下:2.自相关分析我们将绘制时间序列的自相关值。查看acf图中各种滞后值的峰值。对应于第一个重要峰值的滞后可以给出周期的估计。对于这种情况,我们查看50个滞后值并使用statmodels包中的方法绘制acf。从statsmodels.graphics.tsaplotsimportplot_acffig,ax=plt.subplots(figsize=(14,7))plot_acf(record_by_date.values.squeeze(),lags=50,ax=ax,title='Autocorrelation',use_vlines=真的);滞后=列表(范围(51))ax.set_xticks(滞后);ax.set_xticklabels(滞后);从上图可以看出,在7、1、21等处出现了峰值。这证实了我们的时间序列有7天的周期。3.快速傅里叶变换对时间序列进行傅里叶变换,找出主要的频率成分。主频率的倒数可以用作周期的估计。傅立叶变换是一种数学运算,可将复杂信号分解为一组更简单的正弦波和余弦波。傅立叶变换广泛应用于信号处理、通信、图像处理等诸多科学与工程领域。它使我们能够在频域中分析和操作信号,这通常是一种比在时域中更自然、更直观地理解和处理信号的方式。fromscipy.fftimportfft#计算傅里叶变换yf=np.fft.fft(record_by_date)xf=np.linspace(0.0,1.0/(2.0),len(record_by_date)//2)#找到主频率#我们必须删除fft的第一个元素,因为它对应于#DC分量或信号的平均值idx=np.argmax(np.abs(yf[1:len(record_by_date)//2]))freq=xf[idx]period=(1/freq)print(f"时间序列的周期为{period}")的输出为:时间序列的周期为7.030927835051545。这类似于我们使用ACF和目视检查发现的每周周期。4.PeriodogramPeriodogram周期图是信号或序列的功率谱密度(PSD)图。换句话说,它是一个图表,显示每个频率在信号中包含多少总功率。周期图是通过计算信号的傅立叶变换的幅度平方得到的,常用于信号处理和频谱分析中。从某种意义上说,只是前面给出的基于fft的方法的扩展。fromscipy.signalimportperiodogramfreq,power=periodogram(record_by_date)period=1/freq[np.argmax(power)]print(f"时间序列的周期为{period}")plt.plot(freq,power)plt.xlabel('频率(Hz)')plt.ylabel('功率谱密度')plt.show()Periodogram可以清楚的看到信号的最高功率在0.14处,对应周期为7天。为了总结本文,我们提出了三种不同的方法来寻找时间序列中的周期性,通过使用这三种方法,我们能够识别信号的周期性并使用常识来确认它。
