Pilih DataFrame baris antara dua tanggal

Saya menciptakan DataFrame dari csv sebagai berikut:

stock = pd.read_csv('data_in/' + filename + '.csv', skipinitialspace=True)

Yang DataFrame memiliki kolom tanggal. Apakah ada cara untuk membuat yang baru DataFrame (atau hanya menimpa yang sudah ada) yang hanya berisi baris-baris dengan nilai-nilai tanggal yang jatuh dalam rentang tanggal yang ditentukan atau antara dua tanggal yang telah ditentukan, nilai-nilai?

Larutan

Ada dua solusi yang mungkin:

  • Menggunakan boolean masker, kemudian menggunakan df.loc[mask]
  • Mengatur tanggal kolom sebagai DatetimeIndex, maka menggunakan df[start_date : end_date]

Menggunakan boolean masker:

Memastikan df['tanggal'] adalah Seri dengan dtype datetime64[ns]:

df['date'] = pd.to_datetime(df['date'])  

Membuat boolean masker. start_date dan end_date dapat datetime.datetime ini, np.datetime64 ini, `pd.Timestamp ini, atau bahkan datetime string:


#greater than the start date and smaller than the end date
mask = (df['date'] > start_date) & (df['date'] 
Komentar (6)

Saya merasa pilihan terbaik akan menggunakan pemeriksaan langsung daripada menggunakan loc fungsi:


df = df[(df['date'] > '2000-6-1') & (df['date'] 
Komentar (2)

Anda juga dapat menggunakan antara:

df[df.some_date.between(start_date, end_date)]
Komentar (1)

Anda dapat menggunakan isin metode tanggal kolom seperti begitu df[df["tanggal"].isin(pd.date_range(start_date, end_date))]

Catatan: Ini hanya bekerja dengan tanggal (sebagai pertanyaan yang meminta) dan yang tidak timestamps.

Contoh:

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

yang memberikan

           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
Komentar (0)

Menjaga solusi sederhana dan pythonic, saya akan menyarankan anda untuk mencoba ini.

Dalam kasus jika anda akan sering melakukan ini solusi terbaik untuk set pertama kolom tanggal sebagai indeks yang akan mengkonversi kolom di DateTimeIndex dan menggunakan kondisi berikut untuk mengiris setiap rentang tanggal.


import pandas as pd

data_frame = data_frame.set_index('date')

df = data_frame[(data_frame.index > '2017-08-10') & (data_frame.index 
Komentar (0)

Saya memilih untuk tidak mengubah df.

Pilihan untuk mengambil index dari awal dan akhir tanggal:

import numpy as np   
import pandas as pd

#Dummy DataFrame
df = pd.DataFrame(np.random.random((30, 3)))
df['date'] = pd.date_range('2017-1-1', periods=30, freq='D')

#Get the index of the start and end dates respectively
start = df[df['date']=='2017-01-07'].index[0]
end = df[df['date']=='2017-01-14'].index[0]

#Show the sliced df (from 2017-01-07 to 2017-01-14)
df.loc[start:end]

yang menghasilkan:

     0   1   2       date
6  0.5 0.8 0.8 2017-01-07
7  0.0 0.7 0.3 2017-01-08
8  0.8 0.9 0.0 2017-01-09
9  0.0 0.2 1.0 2017-01-10
10 0.6 0.1 0.9 2017-01-11
11 0.5 0.3 0.9 2017-01-12
12 0.5 0.4 0.3 2017-01-13
13 0.4 0.9 0.9 2017-01-14
Komentar (0)

Dengan pengujian panda versi 0.22.0 anda sekarang dapat menjawab pertanyaan ini lebih mudah dengan banyak kode yang dapat dibaca dengan menggunakan antara.

# create a single column DataFrame with dates going from Jan 1st 2018 to Jan 1st 2019
df = pd.DataFrame({'dates':pd.date_range('2018-01-01','2019-01-01')})

Let's mengatakan anda ingin ambil antara tanggal 27 Nov 2018 dan 15 Januari 2019:

# use the between statement to get a boolean mask
df['dates'].between('2018-11-27','2019-01-15', inclusive=False)

0    False
1    False
2    False
3    False
4    False

# you can pass this boolean mask straight to loc
df.loc[df['dates'].between('2018-11-27','2019-01-15', inclusive=False)]

    dates
331 2018-11-28
332 2018-11-29
333 2018-11-30
334 2018-12-01
335 2018-12-02

Perhatikan inklusif argumen. *sangat membantu ketika anda ingin menjadi yang eksplisit tentang jangkauan anda. pemberitahuan ketika diatur ke Benar, kita kembali 27 Nov 2018 serta:

df.loc[df['dates'].between('2018-11-27','2019-01-15', inclusive=True)]

    dates
330 2018-11-27
331 2018-11-28
332 2018-11-29
333 2018-11-30
334 2018-12-01

Metode ini juga lebih cepat dari yang telah disebutkan sebelumnya isin metode:

%%timeit -n 5
df.loc[df['dates'].between('2018-11-27','2019-01-15', inclusive=True)]
868 µs ± 164 µs per loop (mean ± std. dev. of 7 runs, 5 loops each)

%%timeit -n 5

df.loc[df['dates'].isin(pd.date_range('2018-01-01','2019-01-01'))]
1.53 ms ± 305 µs per loop (mean ± std. dev. of 7 runs, 5 loops each)

Namun, ini adalah tidak lebih cepat dari saat ini jawaban yang diterima, yang disediakan oleh unutbu, hanya jika masker sudah dibuat. tapi jika masker yang dinamis dan harus dipindahkan lebih dari dan di atas, metode saya mungkin lebih efisien:


# already create the mask THEN time the function

start_date = dt.datetime(2018,11,27)
end_date = dt.datetime(2019,1,15)
mask = (df['dates'] > start_date) & (df['dates'] 
Komentar (0)