Je crée un DataFrame à partir d'un csv comme suit :
stock = pd.read_csv('data_in/' + filename + '.csv', skipinitialspace=True)
Le DataFrame comporte une colonne date. Existe-t-il un moyen de créer un nouveau DataFrame (ou simplement d'écraser le DataFrame existant) qui ne contient que les lignes dont les valeurs de date sont comprises dans une plage de dates spécifiée ou entre deux valeurs de date spécifiées ?
Il y a deux solutions possibles :
df.loc[mask]
.df[start_date : end_date]
.Utilisation d'un masque booléen :
Assurez-vous que df['date' ;]
est une série avec le dtype datetime64[ns]
:
df['date'] = pd.to_datetime(df['date'])
Créez un masque booléen. start_date
et end_date
peuvent être datetime.datetime
s,
np.datetime64
s, pd.Timestamp
s, ou même des chaînes de dates :
#greater than the start date and smaller than the end date
mask = (df['date'] > start_date) & (df['date'] <= end_date)
Sélectionnez le sous-cadre de données :
df.loc[mask]
ou réaffecter à df
df = df.loc[mask]
Par exemple, python importe numpy comme 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])
donne
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
----------
**Utilisation d'un [DatetimeIndex](https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#partial-string-indexing)** :
Si vous allez faire beaucoup de sélections par date, il peut être plus rapide de mettre la colonne
la colonne `date` comme index d'abord. Ensuite, vous pouvez sélectionner des lignes par date en utilisant
`df.loc[start_date:end_date]`.
``` python
Importez numpy comme 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'])
donne
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
Alors que l'indexation de liste Python, par exemple seq[start:end]
inclut start
mais pas end
, en revanche, Pandas df.loc[start_date : end_date]
inclut les deux points finaux dans le résultat s'ils sont dans l'index. Cependant, ni start_date
ni end_date
ne doivent être dans l'index.
Notez également que [pd.read_csv
possède un paramètre parse_dates
] (http://pandas.pydata.org/pandas-docs/dev/generated/pandas.io.parsers.read_csv.html) que vous pouvez utiliser pour analyser la colonne date
en tant que datetime64
. Ainsi, si vous utilisez parse_dates
, vous n'aurez pas besoin d'utiliser df['date' ;] = pd.to_datetime(df['date' ;])
.
Je pense que la meilleure option sera d'utiliser les contrôles directs plutôt que d'utiliser la fonction loc :
df = df[(df['date'] > '2000-6-1') & (df['date'] <= '2000-6-10')]
Cela fonctionne pour moi.
Le problème majeur avec la fonction loc avec une tranche est que les limites doivent être présentes dans les valeurs réelles, sinon cela entraînera un KeyError.
Vous pouvez utiliser la méthode isin
sur la colonne date
comme suit
`df[df["date" ;].isin(pd.date_range(start_date, end_date))]``
Note: Cela ne fonctionne qu'avec les dates (comme le demande la question) et non avec les timestamps.
Exemple:
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
ce qui donne
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