it-swarm.com.de

Analysieren Sie eine Pandas -Spalte zu Datetime

Ich habe ein DataFrame mit der Spalte date. Wie können wir die 'Datum'-Spalte in ein DateTime-Objekt konvertieren/analysieren?

Ich habe die Datumsspalte mit sql.read_frame() aus einer Postgresql-Datenbank geladen. Ein Beispiel für die Spalte date ist 2013-04-04.

Ich versuche, alle Zeilen in einem Datenrahmen auszuwählen, deren Datumsspalten innerhalb eines bestimmten Zeitraums liegen, z. B. nach 2013-04-01 Und vor 2013-04-04.

Mein Versuch unten gibt den Fehler 'Series' object has no attribute 'read'

Versuch

import dateutil

df['date'] = dateutil.parser.parse(df['date'])

Fehler

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) gibt mir den Fehler AttributeError: 'datetime.date' object has no attribute 'read'

df['date'].truncate(after='2013/04/01') gibt den Fehler TypeError: can't compare datetime.datetime to long

df['date'].dtype Gibt dtype('O') zurück. Ist es bereits ein datetime Objekt?

26
Nyxynyx

pandas liest das schon als datetime Objekt! Sie möchten also Zeilen zwischen zwei Daten auswählen und können dies durch Maskieren tun:

df_masked = df[(df.date > '2012-04-01') & (df.date < '2012-04-04')]

Versuchen Sie Folgendes:

df_masked = df[(df.date > datetime.date(2012,4,1)) & (df.date < datetime.date(2012,4,4))]
5
Ryan Saxe

Pandas kennt das Objekt datetime, aber wenn Sie einige der Importfunktionen verwenden, wird es als Zeichenfolge verwendet. Sie müssen also sicherstellen, dass die Spalte als Datetime-Typ und nicht als Zeichenfolge festgelegt ist. Dann können Sie Ihre Anfrage stellen.

df['date']  = pd.to_datetime(df['date'])
df_masked = df[(df['date'] > datetime.date(2012,4,1)) & (df['date'] < datetime.date(2012,4,4))]
53
Keith

Sie brauchen wahrscheinlich apply, also so etwas wie:

df['date'] = df['date'].apply(dateutil.parser.parse)

Ohne ein Beispiel der Kolumne kann ich nicht garantieren, dass dies funktionieren wird, aber etwas in dieser Richtung sollte Ihnen helfen, weiterzumachen.

4
herrfz

Verwechsle nicht datetime.date mit Pandas pd.Timestamp

Eine "Pandas datetime -Reihe" enthält pd.Timestamp Elemente, nicht datetime.date Elemente. Die empfohlene Lösung für Pandas:

s = pd.to_datetime(s)    # convert series to Pandas
mask = s > '2018-03-10'  # calculate Boolean mask against Pandas-compatible object

Die Top-Antworten haben Probleme:

  • @ RyanSaxes erste Antwort funktioniert nicht. Die zweite Antwort ist ineffizient.
  • Ab Pandas v0.23.0, @ Keiths hochgelobte Antwort funktioniert nicht, es gibt TypeError.

Jede gute Pandas Lösung muss sicherstellen:

  1. Die Reihe ist eine Pandas datetime Reihe, nicht object dTyp.
  2. Die datetime -Reihe wird mit einem kompatiblen Objekt verglichen, z. pd.Timestamp oder Zeichenfolge im richtigen Format.

Hier ist eine Demo mit Benchmarking, die zeigt, dass die einmaligen Umstellungskosten sofort durch einen einzigen Vorgang ausgeglichen werden können:

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

Sie sollten die Elemente durchlaufen und unabhängig analysieren und dann eine neue Liste erstellen.

df['date'] = [dateutil.parser.parse(x) for x in df['date']]
1
ryzhiy