Quand j'essaye ceci:
1996-01-30 10:29:06.
Je m'attends à voir
1996-01-31
mais à la place j'obtiens
>>> a = numpy.datetime64('1995-12-31') >>> b = a + pandas.Timedelta(1, unit='M') >>> print(b)
Une idée pourquoi? Merci beaucoup.
5 Réponses :
Un delta temporel d'un mois est la longueur d'une année divisée par 12.
Vous devez examiner votre date et ajouter la quantité appropriée de jours. Vous pouvez également incrémenter le numéro du mois (en passant à l'année suivante, si nécessaire) et laisser le numéro du jour inchangé.
"Un delta temporel d'un mois est la longueur d'une année divisée par 12." Cela semble être les pandas
(mais pas numpy
) façon de penser.
Vous pouvez remplacer la partie day
pour imiter l'exigence.
import numpy as np import pandas as pd a = np.datetime64('1995-12-31') b = a + pd.Timedelta(1, unit='M') print(b.replace(day=pd.to_datetime(a).day))
Utilisez .date ()
si vous n'êtes intéressé que par la partie date
Il y a une ambiguïté inhérente à l'ajout d'un «mois» à une heure, car les mois varient en longueur.
Créez une date:
In [254]: b = a.item() In [255]: b Out[255]: datetime.date(1995, 12, 31)
en ajoutant des jours à cela fonctionne très bien:
In [251]: a.astype('datetime64[M]') Out[251]: array('1995-12', dtype='datetime64[M]') In [252]: a.astype('datetime64[M]') + np.array(1, 'timedelta64[M]') Out[252]: numpy.datetime64('1996-01')
L'ajout d'un mois génère une erreur:
In [250]: a + np.array(1, 'timedelta64[M]') --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-250-a331f724d7e7> in <module> ----> 1 a + np.array(1, 'timedelta64[M]') TypeError: Cannot get a common metadata divisor for NumPy datetime metadata [D] and [M] because they have incompatible nonlinear base time units
Nous pourrions lancer un
comme un mois - alors cela fonctionne:
In [249]: a + np.array(31, 'timedelta64[D]') Out[249]: numpy.datetime64('1996-01-31')
Changer le mois dans l'objet datetime
correspondant peut être la manière la plus propre de travailler avec ceci: p >
In [247]: a = np.array('1995-12-31','datetime64[D]') In [248]: a Out[248]: array('1995-12-31', dtype='datetime64[D]')
Je n'ai pas suffisamment travaillé avec les objets datetime
pour effectuer le changement sans consulter ses documents.
Une manière concise d'ajouter un mois en laissant le jour inchangé si possible serait de tronquer en mois, d'ajouter 1 puis de lire ce qui a été tronqué:
>>> b = np.minimum((am + 1) + (a - am), (am + 2) - np.timedelta64(1, 'D')) >>> b numpy.datetime64('1995-02-28')
De toute évidence, cela ne fonctionne pas si le le jour d'origine n'existe pas le mois suivant:
>>> a = np.datetime64('1995-01-31') >>> am = a.astype('M8[M]') >>> b = (am + 1) + (a - am) >>> b numpy.datetime64('1995-03-03')
Mais on ne sait pas quelle devrait être la réponse dans ce cas, de toute façon.
Une possibilité serait être au maximum au dernier jour de ce mois:
>>> a = np.datetime64('1995-12-31') >>> am = a.astype('M8[M]') >>> b = (am + 1) + (a - am) >>> b numpy.datetime64('1996-01-31')
Comme déjà mentionné @hpaulj dans sa réponse:
Il y a une ambiguïté inhérente à l'ajout d'un «mois» à une heure, car les mois varient en longueur.
De plus, comme à la version 0.25.0
, Pandas a abandonné le support pour l'utilisation des unités M
(mois) et Y
(années) dans les fonctions Timedelta
.
Mais comme indiqué dans les pandas officiels guide , vous devez utiliser Timedelta pour la durée absolue et DateOffset pour relative durée qui respecte l'arithmétique du calendrier, qui est exactement ce dont nous avons besoin dans votre cas:
Le DateOffset de base agit de manière similaire à
dateutil.relativedelta
( documentation relativedelta ) qui décale une date et une heure de la durée de calendrier correspondante spécifiée.
Donc, en utilisant votre exemple:
In [7]: a = numpy.datetime64('1995-12-31') : b = pandas.Timestamp(a) + pandas.DateOffset(months=1) : b Out[7]: Timestamp('1996-01-31 00:00:00')
NB: vous pouvez toujours utiliser la méthode to_numpy
, si vous avez besoin de convertir pandas.Timestamp à numpy.datetime64
.