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?
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 unDatetimeIndex
, ceci est fondamentalement juste un mince, mais pratique wrapper autour dereindex
qui génère undate_range
et appellereindex
.
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
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'