Hay dos posibles soluciones:
- Use una máscara booleana, luego use
df.loc[mask]
- Establezca la columna de fecha como DatetimeIndex, luego use
df[start_date : end_date]
Usando una máscara booleana :
Asegúrese de que df['date']
sea una serie con dtype datetime64[ns]
:
df['date'] = pd.to_datetime(df['date'])
Haz una máscara booleana. start_date
y end_date
pueden ser cadenas datetime.datetime
s,
np.datetime64
s, pd.Timestamp
s o incluso datetime:
#greater than the start date and smaller than the end date
mask = (df['date'] > start_date) & (df['date'] <= end_date)
Seleccione el sub-DataFrame:
df.loc[mask]
o reasignar a df
df = df.loc[mask]
Por ejemplo,
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])
rendimientos
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
Usando un DatetimeIndex :
Si va a hacer muchas selecciones por fecha, puede ser más rápido establecer date
primero la
columna como índice. Luego puede seleccionar filas por fecha usando
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'])
rendimientos
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
Mientras que la indexación de la lista de Python, por ejemplo, seq[start:end]
incluye start
pero no end
, en contraste, Pandas df.loc[start_date : end_date]
incluye ambos puntos finales en el resultado si están en el índice. Sin embargo, start_date
ni end_date
tiene que estar en el índice.
También tenga en cuenta que pd.read_csv
tiene un parse_dates
parámetro que puede usar para analizar la date
columna como datetime64
s. Por lo tanto, si usa parse_dates
, no necesitaría usar df['date'] = pd.to_datetime(df['date'])
.
df = df.set_index(['date'])
paso, descubrí que el índice también debe ordenarse (a través dedf.sort_index(inplace=True, ascending=True)
), ya que de lo contrario puede obtener resultados de DataFrame menos que completos o incluso vacíosdf.loc['2000-6-1':'2000-6-10']
. Y si lo usaascending=False
, eso no funcionará en absoluto, incluso si lo revierte condf.loc['2000-6-10':'2000-6-1']
Creo que la mejor opción será usar las verificaciones directas en lugar de usar la función loc:
Esto funciona para mi.
El problema principal con la función loc con un segmento es que los límites deben estar presentes en los valores reales, de lo contrario esto dará como resultado KeyError.
fuente
loc
son geniales. Y me parece que, como dice unutbu, ni start_date ni end_date tienen que estar en el índice .También puedes usar
between
:fuente
between_time
: pandas.pydata.org/pandas-docs/version/0.20.3/generated/…Puedes usar el
isin
método en ladate
columna asídf[df["date"].isin(pd.date_range(start_date, end_date))]
Nota: Esto solo funciona con fechas (como se pregunta en la pregunta) y no con marcas de tiempo.
Ejemplo:
lo que da
fuente
Manteniendo la solución simple y pitónica, te sugiero que pruebes esto.
En caso de que vaya a hacer esto con frecuencia, la mejor solución sería establecer primero la columna de fecha como índice, que convertirá la columna en DateTimeIndex y usará la siguiente condición para cortar cualquier rango de fechas.
fuente
Con mi prueba de
pandas
versión0.22.0
, ahora puede responder esta pregunta más fácilmente con un código más legible simplemente usandobetween
.Supongamos que desea obtener las fechas entre el 27 de noviembre de 2018 y el 15 de enero de 2019:
Observe el argumento inclusivo. muy útil cuando quieres ser explícito sobre tu rango. cuando se establece en True, también devolvemos el 27 de noviembre de 2018:
Este método también es más rápido que el
isin
método mencionado anteriormente :Sin embargo, es no más rápido que la respuesta aceptada actualmente, proporcionada por unutbu, sólo si la máscara está ya creado . pero si la máscara es dinámica y necesita reasignarse una y otra vez, mi método puede ser más eficiente:
fuente
Prefiero no alterar el
df
.Una opción es recuperar la
index
de lastart
yend
fechas:lo que resulta en:
fuente
Otra opción, cómo lograr esto, es mediante el
pandas.DataFrame.query()
método. Déjame mostrarte un ejemplo en el siguiente marco de datos llamadodf
.Como argumento, use la condición para filtrar así:
Si no desea incluir límites, simplemente cambie la condición de la siguiente manera:
fuente