0
点赞
收藏
分享

微信扫一扫

Python 中的时间序列分析(含示例)

时间序列是以固定时间间隔记录的一系列观测值。

1. 什么是时间序列?

时间序列是以固定时间间隔记录的一系列观测值。

根据观测频率,时间序列通常可以是每小时、每天、每周、每月、每季度和每年。有时,您可能还有秒和分钟的时间序列,例如每分钟的点击次数和用户访问次数等。

2.为什么要分析时间序列?

因为这是您制定序列预测之前的准备步骤。

此外,时间序列预测具有巨大的商业意义,因为对企业很重要的东西,如需求和销售、网站访问者数量、股价等,本质上都是时间序列数据。

3. 如何在python中导入时间序列?

那么如何在python中导入时间序列数据呢?

时间序列的数据通常以文件或其他电子表格格式存储,并包含两列:日期和测量值。.csv

让我们使用 pandas 包将时间序列数据集(澳大利亚药品销售的 csv 文件)。添加参数将要分析的日期列成为日期字段。read_csv()parse_dates=['date']

from dateutil.parser import parse 
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd
plt.rcParams.update({'figure.figsize': (10, 7), 'figure.dpi': 120})

# Import as Dataframe
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'])
df.head()

Python 中的时间序列分析(含示例)_大数据分析

数据帧时间序列

或者,您可以将其导入为pandas,并将日期作为索引。您只需要在其中指定参数即可执行。index_colpd.read_csv()

ser = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date')
ser.head()

Python 中的时间序列分析(含示例)_大数据分析_02

系列时间序列

请注意,在序列中,“value”列的位置高于日期,以表示它是一个序列。

4. 数据面板

数据面板也是一个基于时间的数据集。

不同之处在于,除了时间序列之外,它还包含一个或多个在相同时间段内测量的相关变量。

通常,数据面板中存在的列包含有助于预测 Y 的解释变量,前提是这些列在未来的预测期间可用。

数据面板示例如下所示。

# 数据源: https://github.com/rouseguy
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/MarketArrivals.csv')
df = df.loc[df.market=='MUMBAI', :]
df.head()

Python 中的时间序列分析(含示例)_可视化时间序列_03

5. 可视化时间序列

让我们使用 matplotlib 来可视化该系列。

# 时间序列数据来源:R 中的 fpp-pacakge。
import matplotlib.pyplot as plt
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date')

# 绘图
def plot_df(df, x, y, title="", xlabel='Date', ylabel='Value', dpi=100):
    plt.figure(figsize=(16,5), dpi=dpi)
    plt.plot(x, y, color='tab:red')
    plt.gca().set(title=title, xlabel=xlabel, ylabel=ylabel)
    plt.show()

plot_df(df, x=df.index, y=df.value,

Python 中的时间序列分析(含示例)_可视化时间序列_04

可视化时间序列

由于所有值均为正值,因此您可以在 Y 轴的两侧显示此值以强调增长。

# Import data
df = pd.read_csv('datasets/AirPassengers.csv', parse_dates=['date'])
x = df['date'].values
y1 = df['value'].values

# 绘制
fig, ax = plt.subplots(1, 1, figsize=(16,5), dpi= 120)
plt.fill_between(x, y1=y1, y2=-y1, alpha=0.5, linewidth=2, color='seagreen')
plt.ylim(-800, 800)
plt.title('Air Passengers (Two Side View)', fontsize=16)
plt.hlines(y=0, xmin=np.min(df.date), xmax=np.max(df.date), linewidth=.5)
plt.show()

Python 中的时间序列分析(含示例)_大数据分析_05

由于它是每月时间序列,并且每年都遵循一定的重复模式,因此您可以将每年绘制为同一图中的单独线。这使您可以并排比较年份模式。

时间序列的季节性图

# Import Data
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date')
df.reset_index(inplace=True)

# 准备
df['year'] = [d.year for d in df.date]
df['month'] = [d.strftime('%b') for d in df.date]
years = df['year'].unique()

# 定义颜色
np.random.seed(100)
mycolors = np.random.choice(list(mpl.colors.XKCD_COLORS.keys()), len(years), replace=False)

# 绘图
plt.figure(figsize=(16,12), dpi= 80)
for i, y in enumerate(years):
    if i > 0:        
        plt.plot('month', 'value', data=df.loc[df.year==y, :], color=mycolors[i], label=y)
        plt.text(df.loc[df.year==y, :].shape[0]-.9, df.loc[df.year==y, 'value'][-1:].values[0], y, fontsize=12, color=mycolors[i])

#修饰
plt.gca().set(xlim=(-0.3, 11), ylim=(2, 30), ylabel='$Drug Sales$', xlabel='$Month$')
plt.yticks(fontsize=12, alpha=.7)
plt.title("Seasonal Plot of Drug Sales Time Series", fontsize=20)
plt.show()

Python 中的时间序列分析(含示例)_大数据分析_06

每年2月的药品销售量急剧下降,3月再次上升,4月再次下降,依此类推。

通过曲线,我们可以看到,这个规律是在给定年的范围内,形成一个固定规律,也就可以作为销售的数据参考。

并且,随着逐年发展,药品销售总体上有所增加。您可以很好地可视化这种趋势以及它每年的变化情况,并绘制出漂亮的逐年变化图。同样,您可以按月绘制箱线图等其他形态来可视化每月分布。

月(季节性)和年度(趋势)分布的箱线图

您可以按季节间隔对数据进行分组,并查看值在给定年份或月份内的分布情况以及随时间推移的比较情况。

# Import Data
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date')
df.reset_index(inplace=True)

# 数据
df['year'] = [d.year for d in df.date]
df['month'] = [d.strftime('%b') for d in df.date]
years = df['year'].unique()

# 绘制
fig, axes = plt.subplots(1, 2, figsize=(20,7), dpi= 80)
sns.boxplot(x='year', y='value', data=df, ax=axes[0])
sns.boxplot(x='month', y='value', data=df.loc[~df.year.isin([1991, 2008]), :])

# 设置
axes[0].set_title('Year-wise Box Plot\n(The Trend)', fontsize=18); 
axes[1].set_title('Month-wise Box Plot\n(The Seasonality)', fontsize=18)
plt.show()

Python 中的时间序列分析(含示例)_稳态串联_07

箱线图使逐年和逐月的分布变得明显。此外,在按月划分的箱线图中,12 月和 1 月的药品销售量明显较高,这可以归因于假日折扣等因素带来的销量拉升。

6. 时间序列中的模式

任何时间序列都可以分为以下部分:基本水平 + 趋势 + 季节性 + 误差

当在时间序列中观察到斜率增加或减少时,将观察到趋势。而当由于季节性因素在定期间隔之间观察到明显的重复模式时,就会观察到季节性。这可能是因为一年中的月份、每月的某一天、工作日甚至一天中的时间。

但是,并非所有时间序列都必须具有趋势和/或季节性。时间序列可能没有明显的趋势,但具有季节性。反之亦然。

因此,时间序列可以被想象为趋势、季节性和误差项的组合。

fig, axes = plt.subplots(1,3, figsize=(20,4), dpi=100)
pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/guinearice.csv', parse_dates=['date'], index_col='date').plot(title='Trend Only', legend=False, ax=axes[0])

pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/sunspotarea.csv', parse_dates=['date'], index_col='date').plot(title='Seasonality Only', legend=False, ax=axes[1])

pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/AirPassengers.csv', parse_dates=['date'], index_col='date').plot(title='Trend and Seasonality', legend=False, ax=axes[2])

Python 中的时间序列分析(含示例)_大数据分析_08

时间序列中的模式

另一个需要考虑的方面是循环行为。当序列中的上升和下降模式没有在基于日历的固定间隔内发生时,就会发生这种情况。应注意不要将“周期性”效应与“季节性”效应混淆。

那么,如何区分“周期性”和“季节性”模式呢?

如果模式不是基于固定日历的频率,那么它是循环的。因为,与季节性不同,周期性效应通常受到业务和其他社会经济因素的影响。

7. 加法和乘法时间序列

根据趋势的性质和季节性,可以将时间序列建模为加法或乘法,其中,序列中的每个观测值都可以表示为各组成部分的总和或乘积:

加法时间序列:
值 = 基本水平 + 趋势 + 季节性 + 误差

乘法时间序列:
值 = 基本水平 x 趋势 x 季节性 x 误差

8. 如何将时间序列分解为它的组成部分?

通过将序列视为基准水平、趋势、季节性指数和残差的加法或乘法组合,可以对时间序列进行经典分解。

seasonal_decomposestatsmodels可以方便地实现这一点。

from statsmodels.tsa.seasonal import seasonal_decompose
from dateutil.parser import parse

# 准备
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date')

# 乘法分解
result_mul = seasonal_decompose(df['value'], model='multiplicative', extrapolate_trend='freq')

# 加法分解
result_add = seasonal_decompose(df['value'], model='additive', extrapolate_trend='freq')

# 绘制
plt.rcParams.update({'figure.figsize': (10,10)})
result_mul.plot().suptitle('Multiplicative Decompose', fontsize=22)
result_add.plot().suptitle('Additive Decompose', fontsize=22)
plt.show()

Python 中的时间序列分析(含示例)_大数据分析_09

设置extrapolate_trend='freq'负责序列开头的趋势和残差中的任何缺失值。

如果你仔细观察添加剂分解的残余物,它会留下一些图案。然而,乘法分解看起来非常随机,这很好。因此,理想情况下,乘法分解应该是这个特定序列的首选。

趋势、季节性和残差分量的数值输出存储在输出本身中。result_mul让我们将它们提取出来并放入数据帧中。

# 提取组件
# 实际值=(季节*趋势*残差)的乘积
df_reconstructed = pd.concat([result_mul.seasonal, result_mul.trend, result_mul.resid, result_mul.observed], axis=1)
df_reconstructed.columns = ['seas', 'trend', 'resid', 'actual_values']
df_reconstructed.head()

9. 稳态和非平稳时间序列

平稳性是时间序列的一个属性。平稳级数是指级数的值不是时间函数的级数。

也就是说,序列的统计属性(如均值、方差和自相关)随时间变化是恒定的。级数的自相关只不过是级数与其先前值的相关性,稍后会详细介绍。

一个没有季节性影响的平稳时间序列 ID。

那么如何识别一个系列是否是静止的呢?让我们举一些例子来说明:

Python 中的时间序列分析(含示例)_可视化时间序列_10

上图来自 R 的 .TSTutorial

那么,为什么平稳系列很重要呢?我为什么要谈论它?

通过应用适当的变换,几乎可以使任何时间序列静止。大多数统计预测方法都设计为处理平稳时间序列。预测过程的第一步通常是进行一些转换,将非平稳序列转换为平稳序列。

9. 如何使时间序列静止?

您可以通过以下方式使系列静止:

  1. 差分系列(一次或多次)
  2. 获取该系列的日志
  3. 取级数的第 n 次方根
  4. 以上组合

平稳化级数的最常见和最方便的方法是至少差分一次级数,直到它变得近似平稳。

那么有什么不同呢?

如果是时间“t”的值,则 Y = Yt – Yt-1 的第一个差值。简单来说,差分序列无非是将下一个值减去当前值。Y_t

如果第一个差异不能使序列静止,则可以选择第二个差异。等等。

例如,请考虑以下系列:[1, 5, 2, 12, 20]

第一个差分给出:[5-1, 2-5, 12-2, 20-12] = [4, -3, 10, 8]

第二个差分给出:[-3-4, -10-3, 8-10] = [-7, -13, -2]

10. 为什么要在预测之前使非平稳序列保持平稳?

预测平稳序列相对容易,预测更可靠。

一个重要原因是,自回归预测模型本质上是线性回归模型,它利用序列本身的滞后作为预测变量。

我们知道,如果预测变量(X 变量)彼此不相关,则线性回归效果最好。因此,平稳化序列解决了这个问题,因为它消除了任何持久的自相关,从而使预测模型中的预测变量(序列的滞后)几乎独立。

既然我们已经确定序列的固定化很重要,那么如何检查给定的序列是否是静止的?

11. 如何测试平稳性?

一个系列的平稳性可以通过像我们之前一样查看系列的情节来建立。

另一种方法是将序列拆分为 2 个或多个连续部分,并计算汇总统计量,如均值、方差和自相关。如果统计数据大不相同,那么该系列不太可能是静止的。

然而,您需要一种方法来定量确定给定序列是否是平稳的。这可以使用称为“单位根测试”的统计测试来完成。这有多种变体,其中测试检查时间序列是否是非平稳的并具有单位根。

测试有多种实现,例如:

  1. ADH 检验
  2. KPSS趋势静止
  3. PP测试

最常用的是 ADH检验,其中原假设是时间序列具有单位根并且是非平稳的。因此,如果 ADH 检验中的 P 值小于显著性水平 (0.05),则拒绝原假设。

另一方面,KPSS 检验用于检验趋势平稳性。原假设和 P 值解释与 ADH 检验正好相反。下面的代码使用 python 中的包实现了这两个测试。statsmodels

from statsmodels.tsa.stattools import adfuller, kpss
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'])

# ADF 测试
result = adfuller(df.value.values, autolag='AIC')
print(f'ADF Statistic: {result[0]}')
print(f'p-value: {result[1]}')
for key, value in result[4].items():
    print('Critial Values:')
    print(f'   {key}, {value}')

# KPSS 测试
result = kpss(df.value.values, regression='c')
print('\nKPSS Statistic: %f' % result[0])
print('p-value: %f' % result[1])
for key, value in result[3].items():
    print('Critial Values:')
    print(f'   {key}, {value}')

输出

ADF Statistic: 3.14518568930674
p-value: 1.0
Critial Values:
   1%, -3.465620397124192
Critial Values:
   5%, -2.8770397560752436
Critial Values:
   10%, -2.5750324547306476

KPSS Statistic: 1.313675
p-value: 0.010000
Critial Values:
   10%, 0.347
Critial Values:
   5%, 0.463
Critial Values:
   2.5%, 0.574
Critial Values:
   1%, 0.739

12. 白噪声和稳态串联有什么区别?

与平稳序列一样,白噪声也不是时间的函数,即其平均值和方差不会随时间变化。但不同的是,白噪声是完全随机的,均值为 0。

在白噪声中,没有任何模式。如果将 FM 收音机中的声音信号视为时间序列,则您在通道之间听到的空白声音是白噪声。

从数学上讲,均值为零的完全随机数序列是白噪声。

randvals = np.random.randn(1000)
pd.Series(randvals).plot(title='Random White Noise', color='k')

Python 中的时间序列分析(含示例)_大数据分析_11

随机白噪声

13. 如何去趋势化时间序列?

去趋势化时间序列是从时间序列中删除趋势分量。但如何提取趋势呢?有多种方法。

  1. 从时间序列中减去最佳拟合线。最佳拟合线可以从以时间步长作为预测变量的线性回归模型中获得。对于更复杂的趋势,您可能需要在模型中使用二次项 (x^2)。
  2. 减去我们之前看到的时间序列分解获得的趋势分量。
  3. 减去平均值
  4. 应用 Baxter-King 过滤器(statsmodels.tsa.filters.bk过滤器)或 Hodrick-Prescott 过滤器(statsmodels.tsa.filters.hp过滤器)等过滤器来删除移动平均趋势线或周期性成分。

让我们实现前两种方法。

# 使用scipy:减去最小拟合线
from scipy import signal
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'])
detrended = signal.detrend(df.value.values)
plt.plot(detrended)
plt.title('Drug Sales detrended by subtracting the least squares fit', fontsize=16)

Python 中的时间序列分析(含示例)_可视化时间序列_12

通过减去最小二乘拟合来消除时间序列的趋势

# 使用统计模型:减去趋势分量
from statsmodels.tsa.seasonal import seasonal_decompose
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date')
result_mul = seasonal_decompose(df['value'], model='multiplicative', extrapolate_trend='freq')
detrended = df.value.values - result_mul.trend
plt.plot(detrended)
plt.title('Drug Sales detrended by subtracting the trend component', fontsize=16)

14. 如何对时间序列进行去季节性化?

还有多种方法可以对时间序列进行去季节性化。以下是一些:

- 1. 以具有长度的移动平均线作为季节窗口。这将在过程中一系列地平滑。

- 2. 季节差异(从当前值减去上一季的值)

- 3. 将序列除以STL分解得到的季节指数

如果除以季节性指数效果不佳,请尝试获取序列的日志,然后进行去季节性化。稍后可以通过取指数来恢复到原始比例。

# 减去趋势分量。
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date')

# 时间序列分解
result_mul = seasonal_decompose(df['value'], model='multiplicative', extrapolate_trend='freq')

# 去季节化
deseasonalized = df.value.values / result_mul.seasonal

# 绘制
plt.plot(deseasonalized)
plt.title('Drug Sales Deseasonalized', fontsize=16)
plt.plot()

Python 中的时间序列分析(含示例)_大数据分析_13

15. 如何测试时间序列的季节性?

常见的方法是绘制序列并在固定时间间隔内检查可重复的模式。因此,季节性的类型由时钟或日历决定:

  1. 一天中的小时
  2. 月份中的某一天
  3. 周刊
  4. 每月
  5. 每年

但是,如果要对季节性进行更明确的检查,请使用自相关函数 (ACF) 图。有关 ACF 的更多信息,请参阅以下部分。但是,当存在强烈的季节性模式时,ACF 图通常会在季节性窗口的倍数处显示明确的重复峰值。

例如,药品销售时间序列是一个月度序列,模式每年重复一次。所以,你可以在12日、24日、36日看到峰值。线。

我必须提醒您,在实际单词数据集中,这种强烈的模式几乎不会被注意到,并且可能会被噪音扭曲,因此您需要仔细观察才能捕获这些模式。

from pandas.plotting import autocorrelation_plot
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv')

# 绘制
plt.rcParams.update({'figure.figsize':(9,5), 'figure.dpi':120})
autocorrelation_plot(df.value.tolist())

Python 中的时间序列分析(含示例)_可视化时间序列_14

16. 如何处理时间序列中的缺失值?

有时,您的时间序列会缺少日期/时间。这意味着,这些时间段的数据没有被捕获或不可用。在那些日子里,测量值可能为零,在这种情况下,您可以用零填充这些期间。

其次,当涉及到时间序列时,通常不应将缺失值替换为序列的平均值,尤其是在序列不是平稳的情况下。对于快速而肮脏的解决方法,您可以做的是向前填充以前的值。

但是,根据系列的性质,您需要在结束之前尝试多种方法。一些有效的插补替代方法是:

  • 向后填充
  • 线性插值
  • 二次插值
  • 最近邻的平均值
  • 季节性 couterparts 的平均值

为了测量插补性能,我手动将缺失值引入时间序列,使用上述方法对其进行插补,然后根据实际值测量插补值的均方误差。

# # 生成数据集
from scipy.interpolate import interp1d
from sklearn.metrics import mean_squared_error
df_orig = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date').head(100)
df = pd.read_csv('datasets/a10_missings.csv', parse_dates=['date'], index_col='date')

fig, axes = plt.subplots(7, 1, sharex=True, figsize=(10, 12))
plt.rcParams.update({'xtick.bottom' : False})

## 1. 初始化 -------------------------------
df_orig.plot(title='Actual', ax=axes[0], label='Actual', color='red', style=".-")
df.plot(title='Actual', ax=axes[0], label='Actual', color='green', style=".-")
axes[0].legend(["Missing Data", "Available Data"])

## 2. 正向填充 --------------------------
df_ffill = df.ffill()
error = np.round(mean_squared_error(df_orig['value'], df_ffill['value']), 2)
df_ffill['value'].plot(title='Forward Fill (MSE: ' + str(error) +")", ax=axes[1], label='Forward Fill', style=".-")

## 3. 向后填充 -------------------------
df_bfill = df.bfill()
error = np.round(mean_squared_error(df_orig['value'], df_bfill['value']), 2)
df_bfill['value'].plot(title="Backward Fill (MSE: " + str(error) +")", ax=axes[2], label='Back Fill', color='firebrick', style=".-")

## 4. 线性插值 ------------------
df['rownum'] = np.arange(df.shape[0])
df_nona = df.dropna(subset = ['value'])
f = interp1d(df_nona['rownum'], df_nona['value'])
df['linear_fill'] = f(df['rownum'])
error = np.round(mean_squared_error(df_orig['value'], df['linear_fill']), 2)
df['linear_fill'].plot(title="Linear Fill (MSE: " + str(error) +")", ax=axes[3], label='Cubic Fill', color='brown', style=".-")

## 5. 三次插值 --------------------
f2 = interp1d(df_nona['rownum'], df_nona['value'], kind='cubic')
df['cubic_fill'] = f2(df['rownum'])
error = np.round(mean_squared_error(df_orig['value'], df['cubic_fill']), 2)
df['cubic_fill'].plot(title="Cubic Fill (MSE: " + str(error) +")", ax=axes[4], label='Cubic Fill', color='red', style=".-")

# 插值参考:
# https://docs.scipy.org/doc/scipy/reference/tutorial/interpolate.html
# https://docs.scipy.org/doc/scipy/reference/interpolate.html

## 6. n个最近近邻的均值 ------
def knn_mean(ts, n):
    out = np.copy(ts)
    for i, val in enumerate(ts):
        if np.isnan(val):
            n_by_2 = np.ceil(n/2)
            lower = np.max([0, int(i-n_by_2)])
            upper = np.min([len(ts)+1, int(i+n_by_2)])
            ts_near = np.concatenate([ts[lower:i], ts[i:upper]])
            out[i] = np.nanmean(ts_near)
    return out

df['knn_mean'] = knn_mean(df.value.values, 8)
error = np.round(mean_squared_error(df_orig['value'], df['knn_mean']), 2)
df['knn_mean'].plot(title="KNN Mean (MSE: " + str(error) +")", ax=axes[5], label='KNN Mean', color='tomato', alpha=0.5, style=".-")

## 7. 季节平均值 ----------------------------
def seasonal_mean(ts, n, lr=0.7):
    """
    Compute the mean of corresponding seasonal periods
    ts: 1D array-like of the time series
    n: Seasonal window length of the time series
    """
    out = np.copy(ts)
    for i, val in enumerate(ts):
        if np.isnan(val):
            ts_seas = ts[i-1::-n]  # previous seasons only
            if np.isnan(np.nanmean(ts_seas)):
                ts_seas = np.concatenate([ts[i-1::-n], ts[i::n]])  # previous and forward
            out[i] = np.nanmean(ts_seas) * lr
    return out

df['seasonal_mean'] = seasonal_mean(df.value, n=12, lr=1.25)
error = np.round(mean_squared_error(df_orig['value'], df['seasonal_mean']), 2)
df['seasonal_mean'].plot(title="Seasonal Mean (MSE: " + str(error) +")", ax=axes[6], label='Seasonal Mean', color='blue', alpha=0.5, style=".-")

Python 中的时间序列分析(含示例)_大数据分析_15

您还可以考虑以下方法,具体取决于您希望插补的准确性。

  1. 如果您有解释变量,请使用预测模型(如随机森林或 k 最近邻)来预测它。
  2. 如果有足够的过去观测值,请预测缺失值。
  3. 如果有足够的未来观测值,请回溯缺失值
  4. 对前几个周期的对应物的预测。


举报

相关推荐

0 条评论