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?
Ada dua solusi yang mungkin:
df.loc[mask]
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'] <= end_date)
Pilih sub-DataFrame:
df.loc[mask]
atau re-assign untuk df
df = df.loc[mask]
Misalnya, `` python impor numpy sebagai np impor panda sebagai pd
df = pd.DataFrame(np.acak.random((200,3))) df['tanggal'] = pd.date_range('2000-1-1', periode=200, freq='D') masker = (df['tanggal'] > '2000-6-1') & (df['tanggal'] <= '2000-6-10') cetak(df.loc[mask]) `` hasil
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
Menggunakan DatetimeIndex:
Jika anda akan melakukan banyak pilihan dengan saat ini, mungkin akan lebih cepat untuk mengatur
tanggal
kolom sebagai index pertama. Kemudian anda dapat memilih baris dengan menggunakan tanggal
df.loc[start_date:end_date]
.
`` python impor numpy sebagai np impor panda sebagai pd
df = pd.DataFrame(np.acak.random((200,3))) df['tanggal'] = pd.date_range('2000-1-1', periode=200, freq='D') df = df.set_index(['tanggal']) cetak(df.loc['2000-6-1':'2000-6-10']) ``
hasil
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
Sementara Python daftar pengindeksan, misal seq[awal:akhir]
termasuk start
tapi tidak end
, sebaliknya, Panda df.loc[start_date : end_date]
termasuk kedua titik akhir dalam hasil jika mereka berada dalam indeks. Tidak start_date
atau end_date
harus di index namun.
Juga perhatikan bahwa pd.read_csv
memiliki parse_dates
parameter yang dapat anda gunakan untuk mengurai tanggal
kolom datetime64 ini. Dengan demikian, jika anda menggunakan
parse_dates, anda tidak akan perlu menggunakan
df['tanggal'] = pd.to_datetime(df['tanggal'])`.
Saya merasa pilihan terbaik akan menggunakan pemeriksaan langsung daripada menggunakan loc fungsi:
df = df[(df['date'] > '2000-6-1') & (df['date'] <= '2000-6-10')]
Ia bekerja untuk saya.
Masalah utama dengan loc fungsi dengan sepotong adalah bahwa batas-batas yang harus hadir dalam nilai yang sebenarnya, jika tidak hal ini akan mengakibatkan KeyError.
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
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 <= '2017-08-15')]
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
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'] <= end_date)
%%timeit -n 5
df.loc[mask]
191 µs ± 28.5 µs per loop (mean ± std. dev. of 7 runs, 5 loops each)