J'ai un DataFrame
avec une colonne nommée date
. Comment convertir/analyser la colonne 'date' en un objet DateTime
?
J'ai chargé la colonne de date à partir d'une base de données Postgresql en utilisant sql.read_frame()
. Un exemple de la colonne date
est 2013-04-04
.
Ce que j'essaie de faire, c'est de sélectionner toutes les lignes d'une trame de données qui ont leurs colonnes de date dans une certaine période, comme après 2013-04-01
Et avant 2013-04-04
.
Ma tentative ci-dessous donne l'erreur 'Series' object has no attribute 'read'
Tentative
import dateutil
df['date'] = dateutil.parser.parse(df['date'])
Erreur
AttributeError Traceback (most recent call last)
<ipython-input-636-9b19aa5f989c> in <module>()
15
16 # Parse 'Date' Column to Datetime
---> 17 df['date'] = dateutil.parser.parse(df['date'])
18
19 # SELECT RECENT SALES
C:\Python27\lib\site-packages\dateutil\parser.pyc in parse(timestr, parserinfo, **kwargs)
695 return parser(parserinfo).parse(timestr, **kwargs)
696 else:
--> 697 return DEFAULTPARSER.parse(timestr, **kwargs)
698
699
C:\Python27\lib\site-packages\dateutil\parser.pyc in parse(self, timestr, default, ignoretz, tzinfos, **kwargs)
299 default = datetime.datetime.now().replace(hour=0, minute=0,
300 second=0, microsecond=0)
--> 301 res = self._parse(timestr, **kwargs)
302 if res is None:
303 raise ValueError, "unknown string format"
C:\Python27\lib\site-packages\dateutil\parser.pyc in _parse(self, timestr, dayfirst, yearfirst, fuzzy)
347 yearfirst = info.yearfirst
348 res = self._result()
--> 349 l = _timelex.split(timestr)
350 try:
351
C:\Python27\lib\site-packages\dateutil\parser.pyc in split(cls, s)
141
142 def split(cls, s):
--> 143 return list(cls(s))
144 split = classmethod(split)
145
C:\Python27\lib\site-packages\dateutil\parser.pyc in next(self)
135
136 def next(self):
--> 137 token = self.get_token()
138 if token is None:
139 raise StopIteration
C:\Python27\lib\site-packages\dateutil\parser.pyc in get_token(self)
66 nextchar = self.charstack.pop(0)
67 else:
---> 68 nextchar = self.instream.read(1)
69 while nextchar == '\x00':
70 nextchar = self.instream.read(1)
AttributeError: 'Series' object has no attribute 'read'
df['date'].apply(dateutil.parser.parse)
me donne l'erreur AttributeError: 'datetime.date' object has no attribute 'read'
df['date'].truncate(after='2013/04/01')
donne l'erreur TypeError: can't compare datetime.datetime to long
df['date'].dtype
Renvoie dtype('O')
. Est-ce déjà un objet datetime
?
pandas le lit déjà comme un objet datetime
! Donc, ce que vous voulez, c'est sélectionner des lignes entre deux dates et vous pouvez le faire en masquant:
df_masked = df[(df.date > '2012-04-01') & (df.date < '2012-04-04')]
Parce que vous avez dit que vous obteniez une erreur de la chaîne pour une raison quelconque, essayez ceci:
df_masked = df[(df.date > datetime.date(2012,4,1)) & (df.date < datetime.date(2012,4,4))]
Pandas connaît la date et l'heure de l'objet, mais lorsque vous utilisez certaines des fonctions d'importation, il est considéré comme une chaîne. Donc, ce que vous devez faire est de vous assurer que la colonne est définie comme le type datetime et non comme une chaîne. Ensuite, vous pouvez faire votre requête.
df['date'] = pd.to_datetime(df['date'])
df_masked = df[(df['date'] > datetime.date(2012,4,1)) & (df['date'] < datetime.date(2012,4,4))]
Vous avez probablement besoin de apply
, donc quelque chose comme:
df['date'] = df['date'].apply(dateutil.parser.parse)
Sans un exemple de colonne, je ne peux pas garantir que cela fonctionnera, mais quelque chose dans ce sens devrait vous aider à continuer.
datetime.date
avec Pandas pd.Timestamp
Une "série Pandas datetime
" contient pd.Timestamp
éléments, pas datetime.date
éléments. La solution recommandée pour Pandas:
s = pd.to_datetime(s) # convert series to Pandas
mask = s > '2018-03-10' # calculate Boolean mask against Pandas-compatible object
Les meilleures réponses ont des problèmes:
TypeError
.Toute bonne Pandas doit assurer:
datetime
series, pas object
dtype.datetime
est comparée à un objet compatible, par ex. pd.Timestamp
, ou chaîne au format correct.Voici une démo avec analyse comparative, démontrant que le coût unique de la conversion peut être immédiatement compensé par une seule opération:
from datetime import date
L = [date(2018, 1, 10), date(2018, 5, 20), date(2018, 10, 30), date(2018, 11, 11)]
s = pd.Series(L*10**5)
a = s > date(2018, 3, 10) # accepted solution #2, inefficient
b = pd.to_datetime(s) > '2018-03-10' # more efficient, including datetime conversion
assert a.equals(b) # check solutions give same result
%timeit s > date(2018, 3, 10) # 40.5 ms
%timeit pd.to_datetime(s) > '2018-03-10' # 33.7 ms
s = pd.to_datetime(s)
%timeit s > '2018-03-10' # 2.85 ms
Vous devez parcourir les éléments et les analyser indépendamment, puis construire une nouvelle liste.
df['date'] = [dateutil.parser.parse(x) for x in df['date']]