Istnieją dwa możliwe rozwiązania:
- Użyj maski logicznej, a następnie użyj
df.loc[mask]
- Ustaw kolumnę daty jako DatetimeIndex, a następnie użyj
df[start_date : end_date]
Za pomocą maski logicznej :
Upewnij się, że df['date']
jest to seria z typem datetime64[ns]
:
df['date'] = pd.to_datetime(df['date'])
Zrób maskę logiczną. start_date
i end_date
może być datetime.datetime
S,
np.datetime64
S, pd.Timestamp
S lub nawet datetime ciągi:
#greater than the start date and smaller than the end date
mask = (df['date'] > start_date) & (df['date'] <= end_date)
Wybierz pod-ramkę danych:
df.loc[mask]
lub ponownie przypisać do df
df = df.loc[mask]
Na przykład,
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])
daje
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
Korzystanie z DatetimeIndex :
Jeśli zamierzasz dokonać wielu wyborów według daty, może być szybciej ustawić
date
kolumnę jako indeks jako pierwszy. Następnie możesz wybrać wiersze według daty za pomocą
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'])
daje
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
Podczas gdy indeksowanie list w Pythonie, np. seq[start:end]
Obejmuje, start
ale nie end
, Pandas df.loc[start_date : end_date]
uwzględnia oba punkty końcowe w wyniku, jeśli są w indeksie. Jednak ani start_date
nie end_date
musi być w indeksie.
Zauważ też, że pd.read_csv
ma parse_dates
parametr, którego można użyć do parsowania date
kolumny jako datetime64
s. Tak więc, jeśli użyjesz parse_dates
, nie będziesz musiał używać df['date'] = pd.to_datetime(df['date'])
.
df = df.set_index(['date'])
kroku odkryłem, że indeks również musi zostać posortowany (przezdf.sort_index(inplace=True, ascending=True)
), ponieważ w przeciwnym razie możesz uzyskać mniej niż pełne lub nawet puste wyniki DataFramedf.loc['2000-6-1':'2000-6-10']
. A jeśli użyjeszascending=False
, to w ogóle nie zadziała, nawet jeślidf.loc['2000-6-10':'2000-6-1']
Wydaje mi się, że najlepszą opcją będzie użycie kontroli bezpośrednich zamiast funkcji loc:
Mi to pasuje.
Głównym problemem związanym z funkcją loc z wycinkiem jest to, że limity powinny występować w rzeczywistych wartościach, jeśli nie, spowoduje to KeyError.
źródło
loc
są świetne. I wydaje mi się, że jak mówi unutbu, ani data początkowa, ani data końcowa nie muszą znajdować się w indeksie .Możesz także użyć
between
:źródło
between_time
: pandas.pydata.org/pandas-docs/version/0.20.3/generated/…Możesz użyć
isin
metody zdate
kolumny w ten sposóbdf[df["date"].isin(pd.date_range(start_date, end_date))]
Uwaga: Działa to tylko z datami (zgodnie z pytaniem), a nie ze znacznikami czasu.
Przykład:
co daje
źródło
Ponieważ rozwiązanie jest proste i pytoniczne, sugeruję wypróbowanie tego.
W przypadku, gdy zamierzasz to robić często najlepszym rozwiązaniem byłoby najpierw ustawić kolumnę daty jako indeks, który przekształci kolumnę w DateTimeIndex i użyje następującego warunku do wycięcia dowolnego zakresu dat.
źródło
Dzięki mojemu testowaniu
pandas
wersji0.22.0
możesz teraz łatwiej odpowiedzieć na to pytanie za pomocą bardziej czytelnego kodu, po prostu używającbetween
.Załóżmy, że chcesz pobrać daty między 27 listopada 2018 r. A 15 stycznia 2019 r .:
Zwróć uwagę na argument włącznie. bardzo pomocne, gdy chcesz wyrazić swoje zdanie na temat swojego zasięgu. zauważ, gdy ustawiony na True, zwracamy również 27 listopada 2018 r .:
Ta metoda jest również szybsza niż poprzednio wspomniana
isin
metoda:Nie jest to jednak szybsze niż obecnie akceptowana odpowiedź dostarczona przez unutbu, tylko jeśli maska jest już utworzona . ale jeśli maska jest dynamiczna i wymaga ciągłego ponownego przypisywania, moja metoda może być bardziej wydajna:
źródło
Wolę nie zmieniać
df
.Opcją jest pobranie
index
zstart
iend
terminach:Co skutkuje w:
źródło
Inną opcją, jak to osiągnąć, jest zastosowanie
pandas.DataFrame.query()
metody. Pokażę ci przykład w następującej ramce danych o nazwiedf
.Jako argument użyj warunku do filtrowania w następujący sposób:
Jeśli nie chcesz uwzględniać granic, po prostu zmień warunek w następujący sposób:
źródło