pandasで時系列データから時刻を指定して行を抽出
pandasで時系列データ(indexがDatetimeIndex)のpandas.DataFrame, Seriesから、特定の時刻の行を抽出するには、at_time()およびbetween_time()メソッドを使う。毎日の決まった時刻のデータを取り出す場合などに便利。
- pandas.DataFrame.at_time — pandas 1.2.3 documentation
- pandas.DataFrame.between_time — pandas 1.2.3 documentation
ここでは以下の内容について説明する。
- 時刻をピンポイントで指定:
at_time() - 時間帯を指定:
between_time()
時系列データの基本については以下の記事を参照。
本記事のサンプルコードではpandas.DataFrameのみを扱うが、pandas.Seriesでも同様のメソッドが提供されている。使い方も同じ。
- pandas.Series.at_time — pandas 1.2.3 documentation
- pandas.Series.between_time — pandas 1.2.3 documentation
時刻をピンポイントで指定: at_time()
以下のpandas.DataFrameを例とする。
import pandas as pd
import datetime
print(pd.__version__)
# 1.2.2
df = pd.DataFrame(range(6), columns=['A'],
index=pd.date_range('2021-01-01', periods=6, freq='8H'))
print(df)
# A
# 2021-01-01 00:00:00 0
# 2021-01-01 08:00:00 1
# 2021-01-01 16:00:00 2
# 2021-01-02 00:00:00 3
# 2021-01-02 08:00:00 4
# 2021-01-02 16:00:00 5
print(type(df.index))
# <class 'pandas.core.indexes.datetimes.DatetimeIndex'>
at_time()もbetween_time()もindexがDatetimeIndexである時系列データのみが対象。print()で同じように表示されていてもindexが文字列の場合は使えないので注意。
第一引数にdatetime.timeオブジェクトを指定すると、その時刻の行が抽出される。
print(datetime.time(8, 0, 0))
# 08:00:00
print(df.at_time(datetime.time(8, 0, 0)))
# A
# 2021-01-01 08:00:00 1
# 2021-01-02 08:00:00 4
該当データが存在しない場合は空のpandas.DataFrameが返される。
print(df.at_time(datetime.time(12, 0, 0)))
# Empty DataFrame
# Columns: [A]
# Index: []
第一引数には時刻を表す文字列を指定することも可能。
print(df.at_time('16:00'))
# A
# 2021-01-01 16:00:00 2
# 2021-01-02 16:00:00 5
print(df.at_time('4PM'))
# A
# 2021-01-01 16:00:00 2
# 2021-01-02 16:00:00 5
時間帯を指定: between_time()
以下のpandas.DataFrameを例とする。
df_sec = pd.DataFrame(range(6), columns=['A'],
index=pd.date_range('2021-01-01', periods=6, freq='8H5s'))
print(df_sec)
# A
# 2021-01-01 00:00:00 0
# 2021-01-01 08:00:05 1
# 2021-01-01 16:00:10 2
# 2021-01-02 00:00:15 3
# 2021-01-02 08:00:20 4
# 2021-01-02 16:00:25 5
at_time()の場合、秒まで正確に一致していないと抽出されない。
print(df_sec.at_time('8:00'))
# Empty DataFrame
# Columns: [A]
# Index: []
print(df_sec.at_time('8:00:00'))
# Empty DataFrame
# Columns: [A]
# Index: []
print(df_sec.at_time('8:00:05'))
# A
# 2021-01-01 08:00:05 1
between_time()を使うと、ピンポイントの時刻ではなく時間帯(幅を持った時間)を指定できる。
第一引数start_timeに開始時刻、第二引数end_timeに終了時刻を指定する。at_time()と同様に、文字列でもdatetime.timeでも指定可能。
print(df_sec.between_time('8:00:00', '8:00:30'))
# A
# 2021-01-01 08:00:05 1
# 2021-01-02 08:00:20 4
print(df_sec.between_time(datetime.time(8, 0, 0), datetime.time(8, 0, 30)))
# A
# 2021-01-01 08:00:05 1
# 2021-01-02 08:00:20 4
start_timeがend_timeよりも後の時刻でもエラーにはならない。start_timeから24時(0時)をまわってend_timeまでの時間帯のデータが抽出される。
print(df_sec.between_time('8:00:30', '8:00:00'))
# A
# 2021-01-01 00:00:00 0
# 2021-01-01 16:00:10 2
# 2021-01-02 00:00:15 3
# 2021-01-02 16:00:25 5
デフォルトではstart_timeとend_timeに指定した時刻も結果に含まれる。引数include_start, include_endをFalseとすると、結果から除外される。
print(df_sec.between_time('8:00:05', '8:00:30'))
# A
# 2021-01-01 08:00:05 1
# 2021-01-02 08:00:20 4
print(df_sec.between_time('8:00:05', '8:00:30', include_start=False))
# A
# 2021-01-02 08:00:20 4