Estoy creando un DataFrame a partir de un csv de la siguiente manera:
stock = pd.read_csv('data_in/' + filename + '.csv', skipinitialspace=True)
El DataFrame tiene una columna de fecha. ¿Hay alguna manera de crear un nuevo DataFrame (o simplemente sobrescribir el existente) que sólo contenga filas con valores de fecha que estén dentro de un rango de fechas especificado o entre dos valores de fecha especificados?
Hay dos soluciones posibles:
df.loc[mask]
.df[fecha_inicial : fecha_final]
.Utilizar una máscara booleana:
Asegúrese de que df['date']
es 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 datetime.datetime
,
np.datetime64
s, pd.Timestamp
s, o incluso cadenas datetime:
#greater than the start date and smaller than the end date
mask = (df['date'] > start_date) & (df['date'] <= end_date)
Seleccione el sub-marco de datos:
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])
produce
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
Utilizando un DatetimeIndex:
Si vas a hacer muchas selecciones por fecha, puede ser más rápido establecer la columna
columna fecha
como índice. Luego puede seleccionar filas por fecha utilizando
df.loc[fecha_inicial:fecha_final]
.
``Python 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'])
produce
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 listas de Python, por ejemplo `seq[start:end]` incluye `start` pero no `end`, en cambio, Pandas `df.loc[start_date : end_date]` incluye *ambos* puntos finales en el resultado si están en el índice. Sin embargo, ni `fecha_inicial` ni `fecha_final` tienen que estar en el índice.
----------
Ten en cuenta también que [`pd.read_csv` tiene un parámetro `parse_dates`](http://pandas.pydata.org/pandas-docs/dev/generated/pandas.io.parsers.read_csv.html) que puedes utilizar para analizar la columna `date` como `datetime64`. Por lo tanto, si utilizas `parse_dates`, no necesitarás utilizar `df['date'] = pd.to_datetime(df['date'])`.
Creo que la mejor opción será utilizar las comprobaciones directas en lugar de utilizar la función loc:
df = df[(df['date'] > '2000-6-1') & (df['date'] <= '2000-6-10')]
A mí me funciona.
El mayor problema con la función loc con una rebanada es que los límites deben estar presentes en los valores reales, si no esto dará lugar a KeyError.
Puedes utilizar el método isin
en la columna date
de la siguiente manera
df[df["fecha"].isin(pd.date_range(fecha_inicial, fecha_final))]
Nota: Esto sólo funciona con fechas (como pide la pregunta) y no con marcas de tiempo.
Ejemplo:
import numpy as np
import pandas as pd
# Make a DataFrame with dates and random numbers
df = pd.DataFrame(np.random.random((30, 3)))
df['date'] = pd.date_range('2017-1-1', periods=30, freq='D')
# Select the rows between two dates
in_range_df = df[df["date"].isin(pd.date_range("2017-01-15", "2017-01-20"))]
print(in_range_df) # print result
que da
0 1 2 date
14 0.960974 0.144271 0.839593 2017-01-15
15 0.814376 0.723757 0.047840 2017-01-16
16 0.911854 0.123130 0.120995 2017-01-17
17 0.505804 0.416935 0.928514 2017-01-18
18 0.204869 0.708258 0.170792 2017-01-19
19 0.014389 0.214510 0.045201 2017-01-20