Jeg opretter et DataFrame fra en csv på følgende måde:
stock = pd.read_csv('data_in/' + filename + '.csv', skipinitialspace=True)
DataFrame har en dato kolonne. Er der en måde at oprette et nyt DataFrame (eller bare overskrive det eksisterende), som kun indeholder rækker med datoværdier, der falder inden for et bestemt datointerval eller mellem to bestemte datoværdier?
Der er to mulige løsninger:
df.loc[mask]
.df[start_date : end_date]
.Anvendelse af en boolsk maske:
Sørg for, at df['date']
er en Series med dtype datetime64[ns]
:
df['date'] = pd.to_datetime(df['date'])
Lav en boolsk maske. start_date
og end_date
kan være datetime.datetime
s,
np.datetime64
s, pd.Timestamp
s, eller endog datotidsstrenge:
#greater than the start date and smaller than the end date
mask = (df['date'] > start_date) & (df['date'] <= end_date)
Vælg sub-DataFrame:
df.loc[mask]
eller gentilknyt til df
df = df.loc[mask]
For eksempel,
import numpy som 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])
```
giver
```
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
```
----------
**Ved brug af et [DatetimeIndex](https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#partial-string-indexing)**:
Hvis du skal foretage en masse markeringer efter dato, kan det være hurtigere at indstille
`date`-kolonnen som indeks først. Derefter kan du vælge rækker efter dato ved hjælp af
`df.loc[start_date:end_date]`.
```` 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'])
```
giver
```
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
```
Mens Pythons listeindeksering, f.eks. `seq[start:end]`, omfatter `start`, men ikke `slut`, omfatter Pandas `df.loc[start_date : end_date]` derimod *begge* slutpunkter i resultatet, hvis de er i indekset. Hverken `start_date` eller `end_date` behøver dog at være i indekset.
----------
Bemærk også, at [`pd.read_csv` har en parameter `parse_dates`](http://pandas.pydata.org/pandas-docs/dev/generated/pandas.io.parsers.read_csv.html), som du kan bruge til at parse `date`-kolonnen som `datetime64`s. Hvis du bruger `parse_dates`, behøver du således ikke at bruge `df['date'] = pd.to_datetime(df['date'])`.
Jeg mener, at den bedste løsning vil være at bruge de direkte kontroller i stedet for at bruge loc-funktionen:
df = df[(df['date'] > '2000-6-1') & (df['date'] <= '2000-6-10')]
Det virker for mig.
Større problem med loc-funktionen med en skive er, at grænserne skal være til stede i de faktiske værdier, hvis ikke dette vil resultere i KeyError.
Du kan bruge metoden isin
på kolonnen date
på følgende måde
df[df["date"].isin(pd.date_range(start_date, end_date))]
Bemærkning: Dette virker kun med datoer (som spørgsmålet spørger) og ikke med tidsstempler.
Eksempel:
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
som giver
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