web-dev-qa-db-fra.com

la fréquence pandas.DatetimeIndex est None et ne peut pas être définie.

J'ai créé un DatetimeIndex à partir d'une colonne "date":

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

Maintenant, l'index se présente comme suit:

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)

Comme vous le voyez, l'attribut freq est None. Je soupçonne que les erreurs sur la route sont causées par la variable freq manquante. Cependant, si j'essaie de définir explicitement la fréquence:

---------------------------------------------------------------------------
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

Donc, apparemment, une fréquence a été déduite, mais elle n'est stockée ni dans les attributs freq ni inferred_freq de DatetimeIndex - les deux ne sont pas. Quelqu'un peut-il éclaircir la confusion?

10
clstaudt

Vous avez deux options ici:

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

Je soupçonne que les erreurs sur la route sont causées par la fréquence manquante.

Tu as tout à fait raison. Voici ce que j'utilise souvent:

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

Un exemple:

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')

Utiliser asfreq réindexera (remplira) les dates manquantes, donc faites attention à cela si ce n'est pas ce que vous recherchez.

La fonction principale pour changer de fréquence est la fonction asfreq . Pour un DatetimeIndex, ceci est fondamentalement juste un mince, mais pratique wrapper autour de reindex qui génère un date_range et appelle reindex.

8
Brad Solomon

Il semble se rapporter à des dates manquantes en tant que notes 3kt. Vous pourrez peut-être "réparer" avec asfreq('D') comme le suggère EdChum, mais cela vous donne un index continu avec des valeurs de données manquantes. Cela fonctionne très bien pour certains exemples de données que j'ai composés:

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)

Notez que freq=None. Si vous appliquez asfreq('D'), ceci devient 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')

Plus généralement, et en fonction de ce que vous essayez exactement de faire, vous pouvez vérifier les options suivantes, telles que la réindexation et le rééchantillonnage: Ajouter des dates manquantes au pandas dataframe

4
JohnE

Je ne sais pas si les versions précédentes de Python ne l'avaient pas, mais 3.6 propose cette solution simple

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