Sto creando un DataFrame da un csv come segue:
stock = pd.read_csv('data_in/' + filename + '.csv', skipinitialspace=True)
Il DataFrame ha una colonna data. C'è un modo per creare un nuovo DataFrame (o semplicemente sovrascrivere quello esistente) che contiene solo righe con valori di data che rientrano in un intervallo di date specificato o tra due valori di data specificati?
Ci sono due possibili soluzioni:
df.loc[mask]
df[start_date : end_date]
Utilizzando una maschera booleana:
Assicurarsi che df['date']
sia una serie con dtype datetime64[ns]
:
df['date'] = pd.to_datetime(df['date'])
Crea una maschera booleana. start_date
e end_date
possono essere datetime.datetime
,
np.datetime64
s, pd.Timestamp
s, o anche stringhe datetime:
#greater than the start date and smaller than the end date
mask = (df['date'] > start_date) & (df['date'] <= end_date)
Seleziona il sub-DataFrame:
df.loc[mask]
o riassegnare a df
df = df.loc[mask]
Per esempio,
importa numpy come np
importare pandas come 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
Utilizzando un DatetimeIndex:
Se avete intenzione di fare molte selezioni per data, potrebbe essere più veloce impostare la colonna
colonna date
come indice. Poi potete selezionare le righe per data usando
df.loc[start_date:end_date]
.
`` python importa numpy come np importare pandas come 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
Mentre l'indicizzazione delle liste di Python, per esempio `seq[start:end]` include `start` ma non `end`, al contrario, Pandas `df.loc[start_date : end_date]` include *entrambi* i punti finali nel risultato se sono nell'indice. Tuttavia, né `start_date` né `end_date` devono essere nell'indice.
----------
Nota anche che [`pd.read_csv` ha un parametro `parse_dates`](http://pandas.pydata.org/pandas-docs/dev/generated/pandas.io.parsers.read_csv.html) che potresti usare per analizzare la colonna `date` come `datetime64`. Quindi, se usi `parse_dates`, non avresti bisogno di usare `df['date'] = pd.to_datetime(df['date'])`.
Sento che l'opzione migliore sarà quella di usare i controlli diretti piuttosto che usare la funzione loc:
df = df[(df['date'] > '2000-6-1') & (df['date'] <= '2000-6-10')]
Per me funziona.
Il problema principale con la funzione loc con una fetta è che i limiti dovrebbero essere presenti nei valori effettivi, se non è così si verificherà un KeyError.
Potete usare il metodo isin
sulla colonna date
in questo modo
df[df["date"].isin(pd.date_range(start_date, end_date))]
Nota: Questo funziona solo con le date (come chiede la domanda) e non con i timestamp.
Esempio:
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
che dà
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