Pandas Dataframe - Löschen bestimmter Stunden des Tages aus 20 Jahren historischer Daten

8

Ich habe Börsendaten für ein einzelnes Wertpapier, die 20 Jahre zurückreichen. Die Daten befinden sich derzeit in einem Pandas DataFrame im folgenden Format:

Geben Sie hier die Bildbeschreibung ein

Das Problem ist, dass ich keine Handelsdaten außerhalb der Geschäftszeiten in meinem DataFrame haben möchte. Der betreffende Markt ist von 9:30 bis 16:00 Uhr (09:30 bis 16:00 Uhr an jedem Handelstag) geöffnet. Ich möchte alle Datenzeilen löschen, die nicht innerhalb dieses Zeitrahmens liegen.

Mein Instinkt ist es, eine Pandas-Maske zu verwenden, die ich zu tun weiß, wenn ich bestimmte Stunden an einem einzigen Tag haben möchte:

mask = (df['date'] > '2015-07-06 09:30:0') & (df['date'] <= '2015-07-06 16:00:0')
sub = df.loc[mask]

Ich habe jedoch keine Ahnung, wie ich eine Daten auf revolvierender Basis verwenden soll, um die Daten für bestimmte Tageszeiten über einen Zeitraum von 20 Jahren zu entfernen.

HMLDude
quelle
Was ist der Datentyp der Spalte date. Könnten Sie diesen Befehl ausführen print(df['date'].map(type)) und seine Ausgabe an die Frage senden?
Andy L.

Antworten:

8

Problem hier ist, wie Sie Daten importieren. Es gibt keine Anzeige, ob 04:00 Uhr oder Uhr ist? Aufgrund Ihrer Kommentare müssen wir jedoch davon ausgehen, dass es sich um eine PM handelt. Die Eingabe zeigt es jedoch als AM an.

Um dies zu lösen, müssen wir zwei Bedingungen in die OR-Klausel aufnehmen.

  1. 9: 30-11: 59
  2. 0: 00-4: 00

Eingang:

df = pd.DataFrame({'date':   {880551: '2015-07-06 04:00:00', 880552: '2015-07-06 04:02:00',880553: '2015-07-06 04:03:00', 880554: '2015-07-06 04:04:00', 880555: '2015-07-06 04:05:00'},
                   'open':   {880551: 125.00, 880552: 125.36,880553: 125.34, 880554: 125.08, 880555: 125.12},
                   'high':   {880551: 125.00, 880552: 125.36,880553: 125.34, 880554: 125.11, 880555: 125.12},
                   'low':    {880551: 125.00, 880552: 125.32,880553: 125.21, 880554: 125.05, 880555: 125.12},
                   'close':  {880551: 125.00, 880552: 125.32,880553: 125.21, 880554: 125.05, 880555: 125.12},
                   'volume': {880551: 141, 880552: 200,880553: 750, 880554: 17451, 880555: 1000},
                   },
                   )


df.head()

    date    open    high    low close   volume
880551  2015-07-06 04:00:00 125.00  125.00  125.00  125.00  141
880552  2015-07-06 04:02:00 125.36  125.36  125.32  125.32  200
880553  2015-07-06 04:03:00 125.34  125.34  125.21  125.21  750
880554  2015-07-06 04:04:00 125.08  125.11  125.05  125.05  17451
880555  2015-07-06 04:05:00 125.12  125.12  125.12  125.12  1000

from datetime import time

start_first = time(9, 30)
end_first = time(11, 59)
start_second = time(0, 00)
end_second = time(4,00)
df['date'] = pd.to_datetime(df['date'])
df= df[(df['date'].dt.time.between(start_first, end_first)) | (df['date'].dt.time.between(start_second, end_second))]
df
date    open    high    low close   volume
880551  2015-07-06 04:00:00 125.0   125.0   125.0   125.0   141

Oben ist keine gute Praxis, und ich rate dringend davon ab, diese Art von mehrdeutigen Daten zu verwenden. Langzeitlösung besteht darin, Daten korrekt mit am / pm zu füllen.

Bei korrektem Datenformat können wir dies auf zwei Arten erreichen:

1) mit datetime

from datetime import time

start = time(9, 30)
end = time(16)
df['date'] = pd.to_datetime(df['date'])
df= df[df['date'].dt.time.between(start, end)]

2) Verwenden zwischen Zeit, die nur mit Datetime Index funktioniert

df['date'] = pd.to_datetime(df['date'])

df = (df.set_index('date')
          .between_time('09:30', '16:00')
          .reset_index())

Wenn Sie immer noch auf Fehler stoßen, bearbeiten Sie Ihre Frage zeilenweise und mit genauem Fehler.

Bhavesh Ghodasara
quelle
Das führt zu folgendem FehlerTypeError: Index must be DatetimeIndex
HMLDude
bearbeitete meine Antwort, df ['date'] = pd.to_datetime (df ['date'])
Bhavesh Ghodasara
Aus diesem SO-Beitrag geht hervor , between_timedass der Datenrahmen ein Datetime-Index sein muss. OP kann es auf DataFrame-Ebene versuchen : day_df = df.set_index('date').between_time('9:30', '16:00').
Parfait
BhaveshGhodasara Ich habe versucht, was Sie in Ihren letzten Änderungen vorgeschlagen haben, und das Ergebnis ist das gleiche TypeError: Index must be DatetimeIndex.
HMLDude
@Parfait Ich habe auch Ihren Vorschlag ausprobiert und noch einmal war die Fehlermeldung : TypeError: Index must be DatetimeIndex.
HMLDude
3

Ich denke, die Antwort ist bereits in den Kommentaren (@ Parfaits .between_time ), aber dass sie bei Debugging-Problemen verloren gegangen ist. Es scheint, dass Ihre df['date']Spalte noch nicht vom Typ Datetimeist.

Dies sollte ausreichen, um dies zu beheben und das erforderliche Ergebnis zu erzielen:

df['date'] = pd.to_datetime(df['date'])
df = df.set_index('date')
df = df.between_time('9:30', '16:00')
jorijnsmit
quelle
0

Dieser Beispielcode fasst die Antworten von Bhavesh Ghodasara, Parfait und jorijnsmit in einem vollständigen, kommentierten Beispiel zusammen:

import pandas as pd

# example dataframe containing 6 records: 2 days of 3 records each in which all cases are covered:
# each day has one record before trading hours, one record during trading hours and one recrod after trading hours
df = pd.DataFrame({'date':   {0: '2015-07-06 08:00:00', 1: '2015-07-06 13:00:00', 2: '2015-07-06 18:00:00', 
                              3: '2015-07-07 08:00:00', 4: '2015-07-07 13:00:00', 5: '2015-07-07 18:00:00'},
                   'open':   {0: 125.00, 1: 125.36, 2: 125.34, 3: 125.08, 4: 125.12, 5: 125.37},
                   'high':   {0: 125.00, 1: 125.36, 2: 125.34, 3: 125.08, 4: 125.12, 5: 125.37},
                   'low':    {0: 125.00, 1: 125.36, 2: 125.34, 3: 125.08, 4: 125.12, 5: 125.37},
                   'close':  {0: 125.00, 1: 125.36, 2: 125.34, 3: 125.08, 4: 125.12, 5: 125.37},
                   'volume': {0: 141, 1: 200, 2: 750, 3: 17451, 4: 1000, 5: 38234},
                   },
                   )

# inspect the example data set
df.head(6)

# first, ensure that the 'date' column is of the correct data type: MAKE IT SO!
df['date'] = pd.to_datetime(df['date'])

# inspect the data types: date column should be of type 'datetime64[ns]'
print(df.dtypes)

# set the index of the dataframe to the datetime-type column 'data'
df = df.set_index('date')

# inspect the index: it should be a DatetimeIndex of dtype 'datetime64[ns]'
print(df.index)

# filter the data set
df_filtered = df.between_time('9:30', '16:00')

# inspect the filtered data set: Voilà! No more outside trading hours records.
df_filtered.head()
Steve
quelle