【问题标题】:pandas.DatetimeIndex frequency is None and can't be setpandas.DatetimeIndex 频率为无且无法设置
【发布时间】:2018-02-23 08:16:46
【问题描述】:

我从“日期”列创建了一个 DatetimeIndex:

sales.index = pd.DatetimeIndex(sales["date"])

现在索引如下:

DatetimeIndex(['2003-01-02', '2003-01-03', '2003-01-04', '2003-01-06',
                   '2003-01-07', '2003-01-08', '2003-01-09', '2003-01-10',
                   '2003-01-11', '2003-01-13',
                   ...
                   '2016-07-22', '2016-07-23', '2016-07-24', '2016-07-25',
                   '2016-07-26', '2016-07-27', '2016-07-28', '2016-07-29',
                   '2016-07-30', '2016-07-31'],
                  dtype='datetime64[ns]', name='date', length=4393, freq=None)

如您所见,freq 属性为无。我怀疑未来的错误是由缺少freq 引起的。但是,如果我尝试明确设置频率:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-148-30857144de81> in <module>()
      1 #### DEBUG
----> 2 sales_train = disentangle(df_train)
      3 sales_holdout = disentangle(df_holdout)
      4 result = sarima_fit_predict(sales_train.loc[5002, 9990]["amount_sold"], sales_holdout.loc[5002, 9990]["amount_sold"])

<ipython-input-147-08b4c4ecdea3> in disentangle(df_train)
      2     # transform sales table to disentangle sales time series
      3     sales = df_train[["date", "store_id", "article_id", "amount_sold"]]
----> 4     sales.index = pd.DatetimeIndex(sales["date"], freq="d")
      5     sales = sales.pivot_table(index=["store_id", "article_id", "date"])
      6     return sales

/usr/local/lib/python3.6/site-packages/pandas/util/_decorators.py in wrapper(*args, **kwargs)
     89                 else:
     90                     kwargs[new_arg_name] = new_arg_value
---> 91             return func(*args, **kwargs)
     92         return wrapper
     93     return _deprecate_kwarg

/usr/local/lib/python3.6/site-packages/pandas/core/indexes/datetimes.py in __new__(cls, data, freq, start, end, periods, copy, name, tz, verify_integrity, normalize, closed, ambiguous, dtype, **kwargs)
    399                                          'dates does not conform to passed '
    400                                          'frequency {1}'
--> 401                                          .format(inferred, freq.freqstr))
    402 
    403         if freq_infer:

ValueError: Inferred frequency None from passed dates does not conform to passed frequency D

显然已经推断出频率,但既没有存储在 DatetimeIndex 的 freq 也没有 inferred_freq 属性中 - 两者都是无。有人能解惑吗?

【问题讨论】:

  • sales.index = pd.DatetimeIndex(sales["date"].asfreq(freq='D')) 工作吗?
  • 没有。 “ValueError:长度不匹配:预期轴有 218153 个元素,新值有 1 个元素”
  • 您的数据样本本身没有频率。判断您提供的信息,缺少 2003-01-05 和 2003-01-12。此外,2003-01-05 + 4393 天是 2015-01-12,而不是 2016-07-31。
  • 我不确定为什么@EdChum 的回答不起作用。也许语法问题?请参阅我的答案,我将asfreq 应用于整个数据框而不仅仅是索引。如果这不是问题,则可能很难说,除非您可以发布一个较小的示例数据框来展示相同的问题。

标签: python pandas indexing time-series


【解决方案1】:

你有几个选择:

  • pd.infer_freq
  • pd.tseries.frequencies.to_offset

我怀疑后面的错误是由缺少频率引起的。

你完全正确。这是我经常使用的:

def add_freq(idx, freq=None):
    """Add a frequency attribute to idx, through inference or directly.

    Returns a copy.  If `freq` is None, it is inferred.
    """

    idx = idx.copy()
    if freq is None:
        if idx.freq is None:
            freq = pd.infer_freq(idx)
        else:
            return idx
    idx.freq = pd.tseries.frequencies.to_offset(freq)
    if idx.freq is None:
        raise AttributeError('no discernible frequency found to `idx`.  Specify'
                             ' a frequency string with `freq`.')
    return idx

一个例子:

idx=pd.to_datetime(['2003-01-02', '2003-01-03', '2003-01-06'])  # freq=None

print(add_freq(idx))  # inferred
DatetimeIndex(['2003-01-02', '2003-01-03', '2003-01-06'], dtype='datetime64[ns]', freq='B')

print(add_freq(idx, freq='D'))  # explicit
DatetimeIndex(['2003-01-02', '2003-01-03', '2003-01-06'], dtype='datetime64[ns]', freq='D')

使用 asfreq 实际上会重新索引(填充)缺失的日期,所以如果这不是您要查找的,请小心。

改变频率的主要函数是asfreq 函数。 对于DatetimeIndex,这基本上只是一个薄的,但方便 围绕reindex 的包装器会生成date_range 并调用reindex

【讨论】:

  • 在 Python 3.7.10 中,此代码会产生错误。具体来说,print(add_freq(idx, freq='D')) 行产生 ValueError: Inferred frequency B from passed values does not conform to passed frequency D
【解决方案2】:

这似乎与 3kt 笔记中缺少的日期有关。正如 EdChum 所建议的那样,您也许可以使用 asfreq('D') 进行“修复”,但这会为您提供一个缺少数据值的连续索引。它适用于我制作的一些示例数据:

df=pd.DataFrame({ 'x':[1,2,4] }, 
   index=pd.to_datetime(['2003-01-02', '2003-01-03', '2003-01-06']) )

df
Out[756]: 
            x
2003-01-02  1
2003-01-03  2
2003-01-06  4

df.index
Out[757]: DatetimeIndex(['2003-01-02', '2003-01-03', '2003-01-06'], 
          dtype='datetime64[ns]', freq=None)

请注意freq=None。如果你申请asfreq('D'),这会变成freq='D'

df.asfreq('D')
Out[758]: 
              x
2003-01-02  1.0
2003-01-03  2.0
2003-01-04  NaN
2003-01-05  NaN
2003-01-06  4.0

df.asfreq('d').index
Out[759]: 
DatetimeIndex(['2003-01-02', '2003-01-03', '2003-01-04', '2003-01-05',
               '2003-01-06'],
              dtype='datetime64[ns]', freq='D')

更一般地说,根据您想要做什么,您可能需要查看以下其他选项,例如重新索引和重新采样:Add missing dates to pandas dataframe

【讨论】:

    【解决方案3】:

    我不确定早期版本的python是否有这个,但是3.6有这个简单的解决方案:

    # 'b' stands for business days
    # 'w' for weekly, 'd' for daily, and you get the idea...
    df.index.freq = 'b' 
    

    【讨论】:

    • 对于我的索引:DatetimeIndex(['2012-12-31', '2013-12-31', '2014-12-31', '2015-12-31', '2016-12-31', '2017-12-31', '2018-12-31', '2019-12-31', '2020-12-31', '2021-12-31', '2022-01-27'], dtype='datetime64[ns]', name='Date', freq=None) 这没有产生任何结果。不知道为什么
    【解决方案4】:

    例如,如果您传递的日期未排序,则可能会发生这种情况。

    看这个例子:

    example_ts = pd.Series(data=range(10),
                           index=pd.date_range('2020-01-01', '2020-01-10', freq='D'))
    example_ts.index = pd.DatetimeIndex(np.hstack([example_ts.index[-1:],
                                                   example_ts.index[:-1]]), freq='D')
    

    由于日期不连续,前面的代码会出现错误。

    example_ts = pd.Series(data=range(10),
                           index=pd.date_range('2020-01-01', '2020-01-10', freq='D'))
    example_ts.index = pd.DatetimeIndex(np.hstack([example_ts.index[:-1],
                                                   example_ts.index[-1:]]), freq='D')
    

    这个运行正确,而不是。

    【讨论】:

      【解决方案5】:

      我不确定,但我遇到了同样的错误。我无法通过上面发布的建议解决我的问题,但使用以下解决方案解决了它。

      Pandas DatetimeIndex + seasonal_decompose = missing frequency.

      最好的问候

      【讨论】:

        猜你喜欢
        • 2018-08-22
        • 2011-12-19
        • 2013-04-29
        • 2023-02-06
        • 1970-01-01
        • 1970-01-01
        • 2016-08-30
        • 1970-01-01
        • 2018-01-05
        相关资源
        最近更新 更多