Pandasで時系列データから時刻を指定して行を抽出!超便利な方法を解説
Pandasは、時系列データを扱う際に非常に強力な機能を提供します。特に、大量の時系列データの中から特定の時刻範囲の行だけを抽出したいというニーズは頻繁に発生します。例えば、一日のうち特定の時間帯のデータだけを分析したい、特定の期間に発生したイベントだけを調べたい、といったケースです。
この記事では、Pandasを使って時系列データから時刻を指定して効率的に行を抽出するさまざまな方法を、具体的なコード例を交えながら丁寧に解説します。
時系列データ抽出の基本
Pandasで時刻情報を持つデータ(DatetimeIndexを持つSeriesやDataFrame)からデータを抽出する際には、Pythonの通常のリストのスライスとは異なる、時系列データならではの便利な機能が用意されています。
サンプルデータの準備
まずは、解説に使うサンプル時系列データを作成しましょう。
import pandas as pd
import numpy as np
# サンプル時系列DataFrameの作成
idx = pd.date_range('2024-07-01 08:00', periods=100, freq='10min')
data = np.random.randint(1, 100, 100)
df = pd.DataFrame({'value': data}, index=idx)
print("元のデータ (一部):\n", df.head())
print("\n元のデータ (tail):\n", df.tail())
特定の「日付」で抽出する
まずは、日付を指定してデータを抽出する方法です。これは最も基本的な抽出方法の一つです。
特定の1日のデータを抽出
文字列で日付を指定するだけで、その日の00:00:00から23:59:59までの全データを抽出できます。
# 2024年7月1日のデータを抽出
df_20240701 = df['2024-07-01']
print("\n2024年7月1日のデータ:\n", df_20240701.head())
print("\n2024年7月1日のデータ (tail):\n", df_20240701.tail())
日付の範囲を指定して抽出(スライス)
日付範囲を指定してスライスすることも可能です。開始日と終了日を文字列で指定するだけで、その期間のデータが抽出されます。Pandasの時系列スライスは、終了日を含みます。
# 2024年7月1日から2024年7月2日までのデータを抽出
df_range_dates = df['2024-07-01':'2024-07-02']
print("\n2024年7月1日から2024年7月2日までのデータ (一部):\n", df_range_dates.head())
print("\n2024年7月1日から2024年7月2日までのデータ (tail):\n", df_range_dates.tail())
特定の「時刻」で抽出する
ここからが本題です。日付だけでなく、時間(時・分・秒)を指定してより細かくデータを抽出する方法です。
特定の時刻までのデータを抽出
日付と時刻を組み合わせてスライスすることで、指定した時刻までのデータを抽出できます。
# 2024年7月1日 12:00までのデータを抽出
df_until_noon = df[:'2024-07-01 12:00']
print("\n2024年7月1日 12:00までのデータ (一部):\n", df_until_noon.head())
print("\n2024年7月1日 12:00までのデータ (tail):\n", df_until_noon.tail())
時刻の範囲を指定して抽出
最もよく使うのが、特定の時間帯(例:午前9時から午後5時まで)のデータを抽出する方法です。
# 2024年7月1日の午前9時から午前11時までのデータを抽出
df_specific_hours = df['2024-07-01 09:00':'2024-07-01 11:00']
print("\n2024年7月1日 午前9時から午前11時までのデータ:\n", df_specific_hours)
at_time
メソッド: 毎日同じ特定の時刻のデータを抽出
at_time
メソッドを使うと、日付に関わらず、毎日同じ特定の時刻のデータを抽出できます。
# 毎日10時00分ちょうど(の最も近いデータ)を抽出
df_at_10am = df.at_time('10:00')
print("\n毎日10時00分ちょうど (の最も近いデータ):\n", df_at_10am)
注意点として、at_time
は指定した時刻に完全に一致するインデックスがない場合、最も近いインデックスのデータを返します(厳密な一致ではない可能性)。
between_time
メソッド: 毎日同じ時刻範囲のデータを抽出
between_time
メソッドは、at_time
の範囲版です。毎日同じ時刻範囲のデータを抽出したい場合に非常に便利です。
# 毎日9時から10時までのデータを抽出
df_between_9_and_10 = df.between_time('09:00', '10:00')
print("\n毎日9時から10時までのデータ (一部):\n", df_between_9_and_10.head())
print("\n毎日9時から10時までのデータ (tail):\n", df_between_9_and_10.tail())
この方法は、例えば「営業時間内」のデータだけを抽出したい、といった場合に重宝します。
条件式と組み合わせて抽出する
より複雑な条件でデータを抽出したい場合は、ブールインデックス(条件式)と組み合わせて抽出することも可能です。
特定の曜日のデータを抽出
インデックスのdt
アクセサを使って、日付や時刻の要素にアクセスし、条件式を適用できます。
# 月曜日のデータを抽出
# サンプルデータには複数の曜日が含まれないので、曜日をチェックする例
# df.index.day_name() で曜日名を取得
# df_mondays = df[df.index.day_name() == 'Monday']
# print("\n月曜日のデータ:\n", df_mondays.head())
# 例として、特定の時間帯かつ特定の曜日を抽出 (サンプルデータの範囲を広げます)
idx_long = pd.date_range('2024-07-01', periods=1000, freq='H') # 長い期間のデータ
df_long = pd.DataFrame({'value': np.random.randint(1, 100, 1000)}, index=idx_long)
# 毎日9時から17時の間にある、かつ、月曜日と水曜日のデータのみを抽出
working_hours = (df_long.index.hour >= 9) & (df_long.index.hour < 17)
week_days = (df_long.index.day_name() == 'Monday') | (df_long.index.day_name() == 'Wednesday')
df_filtered_complex = df_long[working_hours & week_days]
print("\n月曜・水曜の9時~17時のデータ (一部):\n", df_filtered_complex.head())
print("\n月曜・水曜の9時~17時のデータ (tail):\n", df_filtered_complex.tail())
年や月で抽出する
同様に、特定の年や月、四半期のデータを抽出することも可能です。
# 2024年7月のデータを抽出
df_july_2024 = df[df.index.month == 7]
print("\n2024年7月のデータ (一部):\n", df_july_2024.head())
print("\n2024年7月のデータ (tail):\n", df_july_2024.tail())
まとめ
Pandasは、時系列データから特定の時刻を指定して行を抽出するための多様で強力なメソッドを提供します。
文字列による直接スライス:
df['YYYY-MM-DD']
やdf['YYYY-MM-DD HH:MM':'YYYY-MM-DD HH:MM']
で日付・時刻範囲を柔軟に指定。at_time(time)
: 日付に関わらず、毎日特定の時刻のデータを抽出。between_time(start_time, end_time)
: 日付に関わらず、毎日特定の時刻範囲のデータを抽出。条件式と
dt
アクセサ:df[df.index.hour == H]
やdf[df.index.day_name() == 'Day']
のように、より複雑な条件で抽出。
これらの抽出方法を使いこなすことで、時系列データの分析が格段に効率的になり、ビジネスインサイトや傾向の発見に役立つでしょう。ぜひ、ご自身の時系列データでこれらの方法を試してみてください。