Filtrowanie ramek danych Pandas według dat


157

Mam Pandas DataFrame z kolumną „data”. Teraz muszę odfiltrować wszystkie wiersze w DataFrame, które mają daty spoza najbliższych dwóch miesięcy. Zasadniczo muszę zachować tylko te wiersze, które są w ciągu najbliższych dwóch miesięcy.

Jaki jest najlepszy sposób, aby to osiągnąć?

Odpowiedzi:


238

Jeśli indeksem jest kolumna daty , użyj .loc do indeksowania na podstawie etykiet lub .iloc do indeksowania pozycyjnego.

Na przykład:

df.loc['2014-01-01':'2014-02-01']

Zobacz szczegóły tutaj http://pandas.pydata.org/pandas-docs/stable/dsintro.html#indexing-selection

Jeśli kolumna nie jest indeksem , masz dwie możliwości:

  1. Ustaw go jako indeks (tymczasowo lub na stałe, jeśli są to dane szeregów czasowych)
  2. df[(df['date'] > '2013-01-01') & (df['date'] < '2013-02-01')]

Zobacz tutaj, aby uzyskać ogólne wyjaśnienie

Uwaga: plik .ix jest przestarzały.


4
Dziękuję, przeczytam. Data jest osobną kolumną, a nie indeksem w moim przypadku. W pierwszej kolejności powinienem był podać te informacje. MOJE pytanie nie było zbyt pouczające.
AMM

42
Możesz użyć również querytutaj. df.query('20130101 < date < 20130201').
Phillip Cloud

10
Należy wspomnieć, że filtry indeksu (przez .loci .ix) oraz kolumny w przykładach nie są równoważne. df.ix['2014-01-01':'2014-02-01']obejmuje, 2014-02-01podczas gdy df[(df['date'] > '2013-01-01') & (df['date'] < '2013-02-01')]nie obejmuje 2013-02-01, będzie dopasowywać tylko wiersze do 2013-01-31.
Rafael Barbosa

4
To połączenie jest teraz przestarzałe!
Mohamed Taher Alrefaie

6
A co, jeśli nie chcesz filtrować według zakresu dat, ale z wielu dat?
Salem Ben Mabrouk,

53

Z mojego doświadczenia wynika, że ​​poprzednia odpowiedź nie jest poprawna, nie można przekazać jej prostego ciągu, musi to być obiekt typu data-godzina. Więc:

import datetime 
df.loc[datetime.date(year=2014,month=1,day=1):datetime.date(year=2014,month=2,day=1)]

16
Absolutnie mogę przekazać ciąg bez żadnych problemów.
Ninjakannon

9
ix indexer jest przestarzały, użyj loc - pandas.pydata.org/pandas-docs/stable/ ...
Nick

3
pandy przekonwertują dowolny ciąg „datetime” na obiekt datetime .. więc jest to poprawne
janscas

8
Otrzymuję następujący błąd przy użyciu tego: TypeError: „<” nie jest obsługiwany między wystąpieniami „int” i „datetime.date”
Haris Khaliq

41

A jeśli twoje daty są ustandaryzowane poprzez import pakietu datetime, możesz po prostu użyć:

df[(df['date']>datetime.date(2016,1,1)) & (df['date']<datetime.date(2016,3,1))]  

Aby ustandaryzować ciąg daty za pomocą pakietu datetime, możesz użyć tej funkcji:

import datetime
datetime.datetime.strptime

5
Zaleca się użycie df[(df['date']>pd.Timestamp(2016,1,1)) & (df['date']<pd.Timestamp(2016,3,1))].
So

20

Jeśli twoja kolumna datetime ma typ Pandas datetime (np. datetime64[ns]), Do prawidłowego filtrowania potrzebujesz obiektu pd.Timestamp , na przykład:

from datetime import date

import pandas as pd

value_to_check = pd.Timestamp(date.today().year, 1, 1)
filter_mask = df['date_column'] < value_to_check
filtered_df = df[filter_mask]


7

Możesz użyć pd.Timestamp do wykonania zapytania i lokalnego odniesienia

import pandas as pd
import numpy as np

df = pd.DataFrame()
ts = pd.Timestamp

df['date'] = np.array(np.arange(10) + datetime.now().timestamp(), dtype='M8[s]')

print(df)
print(df.query('date > @ts("20190515T071320")')

z wyjściem

                 date
0 2019-05-15 07:13:16
1 2019-05-15 07:13:17
2 2019-05-15 07:13:18
3 2019-05-15 07:13:19
4 2019-05-15 07:13:20
5 2019-05-15 07:13:21
6 2019-05-15 07:13:22
7 2019-05-15 07:13:23
8 2019-05-15 07:13:24
9 2019-05-15 07:13:25


                 date
5 2019-05-15 07:13:21
6 2019-05-15 07:13:22
7 2019-05-15 07:13:23
8 2019-05-15 07:13:24
9 2019-05-15 07:13:25

Zapoznaj się z dokumentacją pand dla DataFrame.query , w szczególności wzmianką o lokalnym @prefiksie udsing, do którego odwołuje się zmienna zmienna . W tym przypadku odwołujemy się pd.Timestampdo lokalnego aliasu, tsaby móc podać ciąg znacznika czasu


Czy mógłbyś przekazać link do dokumentacji funkcji @ts?
Glen Moutrie

6

Więc podczas ładowania pliku danych csv będziemy musieli ustawić kolumnę daty jako indeks teraz, jak poniżej, aby filtrować dane na podstawie zakresu dat. Nie było to potrzebne w przypadku przestarzałej metody: pd.DataFrame.from_csv ().

Jeśli chcesz tylko pokazać dane za dwa miesiące od stycznia do lutego, np. 01.01.2020 do 29.02.2020, możesz to zrobić:

import pandas as pd
mydata = pd.read_csv('mydata.csv',index_col='date') # or its index number, e.g. index_col=[0]
mydata['2020-01-01':'2020-02-29'] # will pull all the columns
#if just need one column, e.g. Cost, can be done:
mydata['2020-01-01':'2020-02-29','Cost'] 

Zostało to przetestowane pod kątem Pythona 3.7. Mam nadzieję, że okaże się to przydatne.


1
index_colmusi być stringnie listą. mydata = pd.read_csv('mydata.csv',index_col='date')
Sharl Sherif

5

Co powiesz na używanie pyjanitor

Ma fajne funkcje.

Po pip install pyjanitor

import janitor

df_filtered = df.filter_date(your_date_column_name, start_date, end_date)

2

Najkrótszy sposób filtrowania ramki danych według daty: załóżmy, że kolumna z datą to typ datetime64 [ns]

# filter by single day
df = df[df['date'].dt.strftime('%Y-%m-%d') == '2014-01-01']

# filter by single month
df = df[df['date'].dt.strftime('%Y-%m') == '2014-01']

# filter by single year
df = df[df['date'].dt.strftime('%Y') == '2014']

1

Nie mogę jeszcze pisać żadnych komentarzy, więc napiszę odpowiedź, jeśli ktoś przeczyta je wszystkie i dotrze do tego.

Jeśli indeks zbioru danych to data i godzina i chcesz przefiltrować go tylko według (na przykład) miesięcy, możesz wykonać następujące czynności:

df.loc[df.index.month = 3]

Spowoduje to przefiltrowanie zbioru danych do marca.


1

Jeśli już przekonwertowałeś ciąg na format daty za pomocą pd.to_datetime, możesz po prostu użyć:

df = df[(df['Date']> "2018-01-01") & (df['Date']< "2019-07-01")]


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.