时间序列的分解():ValueError:您必须指定一个时间段或 x 必须是一个带有 DatetimeIndex 且频率未设置为 None 的 Pandas 对象

新手上路,请多包涵

我在正确执行 additive 模型时遇到一些问题。我有以下数据框:

1个

当我运行这段代码时:

 import statsmodels as sm
import statsmodels.api as sm
decomposition = sm.tsa.seasonal_decompose(df, model = 'additive')
fig = decomposition.plot()
matplotlib.rcParams['figure.figsize'] = [9.0,5.0]

我收到了这条信息:

ValueError:您必须指定句点,或者 x 必须是具有 >DatetimeIndex 且 freq 未设置为 None 的 pandas 对象

我应该怎么做才能得到这个例子:2个

上面的屏幕是我从这个 地方 拿的

原文由 and_and 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 866
2 个回答

具有相同的 ValueError,这只是我自己进行的一些测试和少量研究的结果,并没有声称它是完整的或专业的。请评论或回答任何发现错误的人。

当然,您的数据应该按照索引值的正确顺序排列,正如您在回答中所述,您可以使用 df.sort_index(inplace=True) 来保证这一点。这本身并没有错,尽管错误消息与排序顺序无关,而且我已经检查过:当我对手头的一个巨大数据集的索引进行排序时,错误并没有消失。的确,我还必须对 df.index 进行排序,但是 decompose() 也可以处理未排序的数据,其中项目会及时跳到这里和那里:然后你只会得到很多从左到右和向后的蓝线,直到整个图都充满了它。而且,通常情况下,无论如何排序已经是正确的。就我而言,排序无助于修复错误。因此,我也怀疑索引排序是否已修复您的案例中的错误,因为:错误实际上说明了什么?

ValueError:您必须指定:

  1. [或者]一个时期
  2. 或 x 必须是具有 DatetimeIndex 且 freq 未设置为 None 的 Pandas 对象

首先,如果您有一个 _列表列_,以便您的时间序列嵌套到现在,请参阅 将带有“列表列”中数据的 pandas df 转换为长格式的时间序列。使用三列:[list of data] + [timestamp] + [duration] 了解如何取消嵌套 列表列 的详细信息。 1.) 和 2.) 都需要这样做。

1. 的详细信息:“您必须指定 [任一] 句点……”

期间的定义

来自 https://www.statsmodels.org/stable/generated/statsmodels.tsa.seasonal.seasonal_decompose.html 的“period, int, optional”:

该系列的时期。如果 x 不是 pandas 对象或者 x 的索引没有频率,则必须使用。如果 x 是具有时间序列索引的 pandas 对象,则覆盖 x 的默认周期性。

用整数设置的周期参数表示您希望在数据中出现的周期数。如果您有一个包含 1000 行的 df,其中包含一个 _列表列_(称为 df_nested),并且每个列表包含例如 100 个元素,那么每个循环将有 100 个元素。采取 period = len(df_nested) (= 周期数)以获得季节性和趋势的最佳分割可能是明智的。如果每个周期的元素随时间变化,其他值可能更好。 _我不确定如何正确设置参数,因此问题 statsmodels seasonal_decompose(): What is the right “period of the series” in the context of a list column (constant vs. varying number of items) on Cross Validated which尚未回答。_

选项 1.) 的“period”参数比选项 2.) 有很大的优势。尽管它使用时间索引 (DatetimeIndex) 作为其 x 轴,但与选项 2 相比,它不需要项目准确命中频率。)。相反,它只是将一行中的任何内容连接在一起,优点是您不需要填补任何空白:前一个事件的最后一个值只是与下一个事件的下一个值连接,无论它是否已经在下一秒或第二天。

最大可能的“周期”值是多少?如果你有一个 _列表列_(再次调用 df “ _dfnested “),你应该首先将 列表列 取消嵌套到一个 _普通的列_。最大周期是 len(df_unnested)/2

示例 1:x 中的 20 个项目(x 是 df_unnested 所有项目的数量)最多可以有一个 period = 10

示例 2:拥有 20 件物品并采用 period=20 ,这会引发以下错误:

ValueError: x must have 2 complete cycles requires 40 observations. x 只有 20 个观察值

另一个旁注:为了摆脱有问题的错误, period = 1 应该已经把它拿走了,但是对于时间序列分析,“=1”并没有揭示任何新的东西,每个周期只是 1 个项目然后,趋势与原始数据相同,季节性为0,残差始终为0。

####

示例借自 Convert pandas df with data in a “list column” into a time series in long format。使用三列:[数据列表] + [时间戳] + [持续时间]

 df_test = pd.DataFrame({'timestamp': [1462352000000000000, 1462352100000000000, 1462352200000000000, 1462352300000000000],
                'listData': [[1,2,1,9], [2,2,3,0], [1,3,3,0], [1,1,3,9]],
                'duration_sec': [3.0, 3.0, 3.0, 3.0]})
tdi = pd.DatetimeIndex(df_test.timestamp)
df_test.set_index(tdi, inplace=True)
df_test.drop(columns='timestamp', inplace=True)
df_test.index.name = 'datetimeindex'

df_test = df_test.explode('listData')
sizes = df_test.groupby(level=0)['listData'].transform('size').sub(1)
duration = df_test['duration_sec'].div(sizes)
df_test.index += pd.to_timedelta(df_test.groupby(level=0).cumcount() * duration, unit='s')

结果 df_test[‘listData’] 如下所示:

 2016-05-04 08:53:20    1
2016-05-04 08:53:21    2
2016-05-04 08:53:22    1
2016-05-04 08:53:23    9
2016-05-04 08:55:00    2
2016-05-04 08:55:01    2
2016-05-04 08:55:02    3
2016-05-04 08:55:03    0
2016-05-04 08:56:40    1
2016-05-04 08:56:41    3
2016-05-04 08:56:42    3
2016-05-04 08:56:43    0
2016-05-04 08:58:20    1
2016-05-04 08:58:21    1
2016-05-04 08:58:22    3
2016-05-04 08:58:23    9

现在看看不同时期的整数值。

period = 1 :

 result_add = seasonal_decompose(x=df_test['listData'], model='additive', extrapolate_trend='freq', period=1)
plt.rcParams.update({'figure.figsize': (5,5)})
result_add.plot().suptitle('Additive Decompose', fontsize=22)
plt.show()

在此处输入图像描述

period = 2

 result_add = seasonal_decompose(x=df_test['listData'], model='additive', extrapolate_trend='freq', period=2)
plt.rcParams.update({'figure.figsize': (5,5)})
result_add.plot().suptitle('Additive Decompose', fontsize=22)
plt.show()

在此处输入图像描述

如果您将所有项目的四分之一作为一个周期,则此处为 4(共 16 个项目)。

period = 4

 result_add = seasonal_decompose(x=df_test['listData'], model='additive', extrapolate_trend='freq', period=int(len(df_test)/4))
plt.rcParams.update({'figure.figsize': (5,5)})
result_add.plot().suptitle('Additive Decompose', fontsize=22)
plt.show()

在此处输入图像描述

或者,如果您在此处采用循环的最大可能大小,即 8(共 16 个项目)。

period = 8 :

 result_add = seasonal_decompose(x=df_test['listData'], model='additive', extrapolate_trend='freq', period=int(len(df_test)/2))
plt.rcParams.update({'figure.figsize': (5,5)})
result_add.plot().suptitle('Additive Decompose', fontsize=22)
plt.show()

在此处输入图像描述

看看 y 轴如何改变它们的比例。

####

您将根据需要增加周期整数。你的问题的最大值:

 sm.tsa.seasonal_decompose(df, model = 'additive', period = int(len(df)/2))

2. 的详细信息:“…或 x 必须是具有 DatetimeIndex 且频率未设置为 None 的熊猫对象”

要使 x 成为频率未设置为 None 的 DatetimeIndex,您需要使用 .asfreq(‘?’) 和 ?在 https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#offset-aliases 中的各种偏移别名中进行选择。

在您的情况下,此选项 2. 更适合,因为您似乎有一个没有间隙的列表。然后,您的月度数据可能应该作为“月开始频率”引入——>“MS”作为偏移量别名:

 sm.tsa.seasonal_decompose(df.asfreq('MS'), model = 'additive')

请参阅 如何使用 pd.to_datetime() 设置频率? 有关更多详细信息,以及您将如何处理差距。

如果您的数据在时间上高度分散,以至于有太多的间隙需要填补,或者如果时间上的间隙并不重要,那么使用“period”的选项 1 可能是更好的选择。

在我的 df_test 示例中,选项 2 并不好。数据在时间上完全分散,如果我以秒为频率,你会得到:

df_test.asfreq('s') 的输出(=以秒为单位的频率):

 2016-05-04 08:53:20      1
2016-05-04 08:53:21      2
2016-05-04 08:53:22      1
2016-05-04 08:53:23      9
2016-05-04 08:53:24    NaN
                      ...
2016-05-04 08:58:19    NaN
2016-05-04 08:58:20      1
2016-05-04 08:58:21      1
2016-05-04 08:58:22      3
2016-05-04 08:58:23      9
Freq: S, Name: listData, Length: 304, dtype: object

您在这里看到,虽然我的数据只有 16 行,但引入以秒为单位的频率会强制 df 为 304 行,只能从“08:53:20”延伸到“08:58:23”,这里造成 288 个间隙.更重要的是,在这里你必须准确的时间。如果你有 0.1 甚至 0.12314 秒作为你的实际频率,你将不会用你的索引命中大部分项目。

这是一个以 min 作为偏移量别名的示例, df_test.asfreq('min')

 2016-05-04 08:53:20      1
2016-05-04 08:54:20    NaN
2016-05-04 08:55:20    NaN
2016-05-04 08:56:20    NaN
2016-05-04 08:57:20    NaN
2016-05-04 08:58:20      1

我们看到只有第一分钟和最后一分钟被填满,其余的都没有被击中。

以天为偏移别名, df_test.asfreq('d')

 2016-05-04 08:53:20    1

我们看到您只得到第一行作为结果 df,因为只涵盖了一天。它会给你找到的第一个项目,其余的都被丢弃。

一切的结束

将所有这些放在一起,在您的情况下,选择选项 2,而在我的 df_test 示例中,需要选项 1。

原文由 questionto42standswithUkraine 发布,翻译遵循 CC BY-SA 4.0 许可协议

原因可能是您的数据存在差距。例如:

在此处输入图像描述

此数据有差距,会导致 seasonal_decompose() 方法出现异常

在此处输入图像描述

这个数据不错,所有天都覆盖了,不会抛出Exception

原文由 Viacheslav Plekhanov 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏