Es gibt zwei mögliche Lösungen:
- Verwenden Sie eine boolesche Maske und dann
df.loc[mask]
- Legen Sie die Datumsspalte als DatetimeIndex fest und verwenden Sie sie
df[start_date : end_date]
Verwenden einer Booleschen Maske :
Stellen Sie sicher, dass df['date']
es sich um eine Serie mit dem Typ dtype handelt datetime64[ns]
:
df['date'] = pd.to_datetime(df['date'])
Machen Sie eine boolesche Maske. start_date
und end_date
kann datetime.datetime
s,
np.datetime64
s, pd.Timestamp
s oder sogar datetime-Zeichenfolgen sein:
#greater than the start date and smaller than the end date
mask = (df['date'] > start_date) & (df['date'] <= end_date)
Wählen Sie den Sub-DataFrame aus:
df.loc[mask]
oder neu zuweisen df
df = df.loc[mask]
Beispielsweise,
import numpy as np
import pandas as pd
df = pd.DataFrame(np.random.random((200,3)))
df['date'] = pd.date_range('2000-1-1', periods=200, freq='D')
mask = (df['date'] > '2000-6-1') & (df['date'] <= '2000-6-10')
print(df.loc[mask])
ergibt
0 1 2 date
153 0.208875 0.727656 0.037787 2000-06-02
154 0.750800 0.776498 0.237716 2000-06-03
155 0.812008 0.127338 0.397240 2000-06-04
156 0.639937 0.207359 0.533527 2000-06-05
157 0.416998 0.845658 0.872826 2000-06-06
158 0.440069 0.338690 0.847545 2000-06-07
159 0.202354 0.624833 0.740254 2000-06-08
160 0.465746 0.080888 0.155452 2000-06-09
161 0.858232 0.190321 0.432574 2000-06-10
Verwenden eines DatetimeIndex :
Wenn Sie viele Auswahlen nach Datum vornehmen, ist es möglicherweise schneller, die
date
Spalte zuerst als Index festzulegen. Dann können Sie Zeilen nach Datum mit auswählen
df.loc[start_date:end_date]
.
import numpy as np
import pandas as pd
df = pd.DataFrame(np.random.random((200,3)))
df['date'] = pd.date_range('2000-1-1', periods=200, freq='D')
df = df.set_index(['date'])
print(df.loc['2000-6-1':'2000-6-10'])
ergibt
0 1 2
date
2000-06-01 0.040457 0.326594 0.492136 # <- includes start_date
2000-06-02 0.279323 0.877446 0.464523
2000-06-03 0.328068 0.837669 0.608559
2000-06-04 0.107959 0.678297 0.517435
2000-06-05 0.131555 0.418380 0.025725
2000-06-06 0.999961 0.619517 0.206108
2000-06-07 0.129270 0.024533 0.154769
2000-06-08 0.441010 0.741781 0.470402
2000-06-09 0.682101 0.375660 0.009916
2000-06-10 0.754488 0.352293 0.339337
Während die Python-Listenindizierung, z. B. seq[start:end]
enthält, start
aber nicht end
, df.loc[start_date : end_date]
enthält Pandas beide Endpunkte im Ergebnis, wenn sie im Index enthalten sind. Weder start_date
noch end_date
muss es jedoch im Index sein.
Beachten Sie auch, dass pd.read_csv
es einen parse_dates
Parameter gibt, mit dem Sie die date
Spalte als datetime64
s analysieren können . Wenn Sie also verwenden parse_dates
, müssen Sie nicht verwenden df['date'] = pd.to_datetime(df['date'])
.
df = df.set_index(['date'])
Schritt habe ich festgestellt, dass der Index auch sortiert werden muss (viadf.sort_index(inplace=True, ascending=True)
), da Sie sonst weniger als vollständige oder sogar leere DataFrame-Ergebnisse erhalten könnendf.loc['2000-6-1':'2000-6-10']
. Und wenn Sie verwendenascending=False
, wird das überhaupt nicht funktionieren, selbst wenn Sie es mitdf.loc['2000-6-10':'2000-6-1']
Ich bin der Meinung, dass die beste Option darin besteht, die direkten Überprüfungen anstelle der loc-Funktion zu verwenden:
Für mich geht das.
Das Hauptproblem bei der loc-Funktion mit einem Slice besteht darin, dass die Grenzwerte in den tatsächlichen Werten vorhanden sein sollten. Andernfalls führt dies zu KeyError.
quelle
loc
großartig. Und es scheint mir, dass, wie unutbu sagt, weder start_date noch end_date im Index enthalten sein müssen .Sie können auch verwenden
between
:quelle
between_time
: pandas.pydata.org/pandas-docs/version/0.20.3/generated/…Sie können die
isin
Methode für diedate
Spalte wie folgt verwendendf[df["date"].isin(pd.date_range(start_date, end_date))]
Hinweis: Dies funktioniert nur mit Datumsangaben (wie in der Frage gestellt) und nicht mit Zeitstempeln.
Beispiel:
was gibt
quelle
Um die Lösung einfach und pythonisch zu halten, würde ich Ihnen empfehlen, dies zu versuchen.
Wenn Sie dies häufig tun, besteht die beste Lösung darin, zuerst die Datumsspalte als Index festzulegen, der die Spalte in DateTimeIndex konvertiert, und die folgende Bedingung zu verwenden, um einen beliebigen Datumsbereich aufzuteilen.
quelle
Mit meinem
pandas
Versionstest können0.22.0
Sie diese Frage jetzt einfacher mit besser lesbarem Code beantworten, indem Sie einfach verwendenbetween
.Angenommen, Sie möchten die Daten zwischen dem 27. November 2018 und dem 15. Januar 2019 erfassen:
Beachten Sie das inklusive Argument. Sehr hilfreich, wenn Sie Ihre Reichweite explizit angeben möchten. Beachten Sie, wenn wir auf True gesetzt sind, kehren wir auch am 27. November 2018 zurück:
Diese Methode ist auch schneller als die zuvor erwähnte
isin
Methode:Es ist jedoch nicht schneller als die aktuell akzeptierte Antwort von unutbu, nur wenn die Maske bereits erstellt wurde . Wenn die Maske jedoch dynamisch ist und immer wieder neu zugewiesen werden muss, ist meine Methode möglicherweise effizienter:
quelle
Ich ziehe es vor, das nicht zu ändern
df
.Eine Option ist das Abrufen
index
derstart
undend
-Daten:was in ... endet:
quelle
Eine andere Möglichkeit, dies zu erreichen, ist die Verwendung der
pandas.DataFrame.query()
Methode. Lassen Sie mich Ihnen ein Beispiel für den folgenden Datenrahmen zeigendf
.Verwenden Sie als Argument die Bedingung zum Filtern wie folgt:
Wenn Sie keine Grenzen einschließen möchten, ändern Sie die Bedingung wie folgt:
quelle