gpt4 book ai didi

python - 分解()时间序列 : ValueError: You must specify a period or x must be a pandas object with a DatetimeIndex with a freq not set to None

转载 作者:行者123 更新时间:2023-12-04 04:25:35 30 4
gpt4 key购买 nike

正确执行加法模型有一些问题。
我有那个数据框:
enter image description here
当我运行此代码时:

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 且频率未设置为 None 的 Pandas 对象
我应该怎么做才能得到那个例子:
enter image description here
上面的屏幕是我从这个地方拍的 https://towardsdatascience.com/analyzing-time-series-data-in-pandas-be3887fdd621

最佳答案

具有相同的 ValueError,这只是我自己的一些测试和少量研究的结果,并没有声称它是完整或专业的。请评论或回答任何发现错误的人。
当然,您的数据应该按索引值的正确顺序排列,您可以使用 df.sort_index(inplace=True) 来保证这一点。 ,正如您在回答中所述。这本身并没有错,尽管错误消息与排序顺序无关,而且我已经检查过这一点:在我对手头的巨大数据集的索引进行排序时,错误不会消失。是的,我也必须对 df.index 进行排序,但是分解()也可以处理未排序的数据以及项目在此处和那里及时跳转的情况:然后您只需从左到右再向后得到很多蓝线,直到整个图形都充满它。更重要的是,通常,排序已经是正确的顺序了。就我而言,排序无助于修复错误。因此,我也怀疑索引排序是否修复了您的情况下的错误,因为:错误实际上说明了什么?
值错误:您必须指定:

  • [要么]一个时期
  • 或者 x 必须是一个带有 DatetimeIndex 且频率未设置为 None 的 pandas 对象

  • 首先,如果您有一个列表列以便您的时间序列嵌套到现在,请参阅 Convert pandas df with data in a "list column" into a time series in long format. Use three columns: [list of data] + [timestamp] + [duration]有关如何取消嵌套列表列的详细信息。这对于 1.) 和 2.) 都是需要的。
    1.的详细信息:“您必须指定[或]一个句点......”
    期间的定义
    “句点,整数,可选”来自 https://www.statsmodels.org/stable/generated/statsmodels.tsa.seasonal.seasonal_decompose.html :

    Period of the series. Must be used if x is not a pandas object or ifthe index of x does not have a frequency. Overrides defaultperiodicity of x if x is a pandas object with a timeseries index.


    用整数设置的 period 参数表示您希望在数据中出现的周期数。如果您的 df 有 1000 行,其中有一个列表列(称为 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)在尚未回答的交叉验证上。
    选项 1.) 的“期间”参数比选项 2.) 有很大的优势。尽管它使用时间索引 (DatetimeIndex) 作为其 x 轴,但与选项 2 相比,它不需要项目准确地达到频率。)。相反,它只是将一行中的任何内容连接在一起,优点是您不需要填充任何间隙:前一个事件的最后一个值只是与下一个事件的下一个值连接,无论它是否已经在下一秒或第二天。
    最大可能的“周期”值是多少?如果您有一个列表列(再次调用 df“df_nested”),您应该首先将列表列取消嵌套到一个普通列。最大周期为 len(df_unnested)/2 .
    Example1:x 中的 20 个项目(x 是 df_unnested 的所有项目的数量)最大可以有 period = 10 .
    示例 2:有 20 个项目并取 period=20相反,这会引发以下错误:

    ValueError: x must have 2 complete cycles requires 40observations. x only has 20 observation(s)


    另一个旁注:
    要消除有问题的错误, period = 1应该已经把它拿走了,但是对于时间序列分析,“=1”并没有揭示任何新东西,每个周期只有1个项目,趋势与原始数据相同,季节性为0,残差始终为0.
    ####
    示例借自 Convert pandas df with data in a "list column" into a time series in long format. Use three columns: [list of data] + [timestamp] + [duration]
    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()
    enter image description here 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()
    enter image description here
    如果您将所有项目的四分之一作为一个周期,这里是 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()
    enter image description here
    或者,如果您在此处采用循环的最大可能大小,即 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()
    enter image description here
    看看 y 轴如何改变它们的比例。
    ####
    您将根据需要增加周期整数。您的问题的最大值:
    sm.tsa.seasonal_decompose(df, model = 'additive', period = int(len(df)/2))
    2. 的详细信息:“... 或 x 必须是一个带有 DatetimeIndex 且频率未设置为 None 的 Pandas 对象”
    要使 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')
    How to set frequency with pd.to_datetime()?有关更多详细信息,以及有关如何处理差距的信息。
    如果您的数据在时间上高度分散,以至于有太多空白需要填补,或者如果时间空白并不重要,则使用“句点”的选项 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。

    关于python - 分解()时间序列 : ValueError: You must specify a period or x must be a pandas object with a DatetimeIndex with a freq not set to None,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60017052/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com