この記事は Qiita Advent Calendar 2025 - 時系列データ の21日目の記事です。
はじめに
パターン抽出の特許の使い道を示すために、論文とかにはならないだろうけど使い方のヒントになるような記事を書こうと思い立ち投稿します。
本来ならば、webアクセスで一か月程度空いて再度アクセスしてきた人の検出に使おうと考えていたのですが、データ持ってないので、気温データで真夏と暑めの夜が続きそうな場合の検出に使おうと思っています。
簡易的な異常検知などでも使えるのではないかと思っています。
※そのまま使うと、アクセスし続ける人も検出します。
手法に関しては、数式を書いた記事と、図で説明した記事があるので読んでください。
データ
気象庁のデータ(ダウンロード先リンク)を使って、東京と釧路市阿寒湖畔に最高気温が25度以上かつ、最低気温が20度以上の日が、三日続く事が何度あるか計算したいと思います。
処理方法
- 最高気温が25度以上かつ、最低気温が20度以上の日を計算し3日続く日を計算する
- 提案している相関を用いて、72時間で12時間おきに25度以上と20度以上の気温になっている日を計算する
の二つ用意します。
条件違うので違う日数になりますが、大体同じような日数がでてきます。
実際に処理をしてみる
前処理
提案している相関で大小を見たいときは、負の値無い方が、都合がいいので絶対温度にしています。
import numpy as np
import pandas as pd
from bedcmm import pattern as bedcmm
import matplotlib.pyplot as plt
import statsmodels.api as sm
# load data
df_tokyo = pd.read_csv('sample_data/data_東京_utf-8.csv',skiprows=4)
df_akankohan = pd.read_csv('sample_data/data_釧路市阿寒湖畔_utf-8.csv',skiprows=4)
# 欠損値補完
df_tokyo.iloc[:,1] = df_tokyo.iloc[:,1].interpolate(method='linear')
df_akankohan.iloc[:,1] = df_akankohan.iloc[:,1].interpolate(method='linear')
# 絶対温度化
K_cont = 273.15
np_temp_tokyo = np.array(df_tokyo.iloc[:,1]) + K_cont
np_temp_akankohan = np.array(df_akankohan.iloc[:,1]) + K_cont
気温の生データ
1. 最高気温が25度以上かつ、最低気温が20度以上の日を計算し3日続く日を計算する
単純に最高気温と最低気温を出して計算すると以下のようになります。
max_temp_day_tokyo = np.array([np.max(np_temp_tokyo[i*24:i*24+24]) for i in range(int(len(np_temp_tokyo)/24))])
min_temp_day_tokyo = np.array([np.min(np_temp_tokyo[i*24:i*24+24]) for i in range(int(len(np_temp_tokyo)/24))])
max_temp_day_akankohan = np.array([np.max(np_temp_akankohan[i*24:i*24+24]) for i in range(int(len(np_temp_akankohan)/24))])
min_temp_day_akankohan = np.array([np.min(np_temp_akankohan[i*24:i*24+24]) for i in range(int(len(np_temp_akankohan)/24))])
hot_night_day_tokyo = (max_temp_day_tokyo>max_temp_thre) & (min_temp_day_tokyo>min_temp_thre)
hot_night_day_tokyo_cont3 = [np.sum(hot_night_day_tokyo[i:i+3])==3 for i in range(366-3)]
hot_night_day_akankohan = (max_temp_day_akankohan>max_temp_thre) & (min_temp_day_akankohan>min_temp_thre)
hot_night_day_akankohan_cont3 = [np.sum(hot_night_day_akankohan[i:i+3])==3 for i in range(366-3)]
print(f"tokyo min max temp cont hot 3 days:{np.sum(hot_night_day_tokyo_cont3)}/{len(hot_night_day_tokyo_cont3)}")
print(f"akankohan min max temp cont hot 3 days:{np.sum(hot_night_day_akankohan_cont3)}/{len(hot_night_day_akankohan_cont3)}")
tokyo min max temp cont hot 3 days:86/363
akankohan min max temp cont hot 3 days:0/363
いやぁ、阿寒湖畔の方が涼しいですね。
2. 提案している相関を用いて、72時間で12時間おきに25度以上と20度以上の気温になっている日を計算する
12時間おきに、基底を以下のように設定してやると、12時間おきに値が指定値以上になるかチェックできます。
相関を取得して、1以上になれば指定の温度以上の場合になります。
base = np.array([max_temp_thre,max_temp_thre,0,0,0,0,0,0,0,0,0,0,
min_temp_thre,min_temp_thre,0,0,0,0,0,0,0,0,0,0,
max_temp_thre,max_temp_thre,0,0,0,0,0,0,0,0,0,0,
min_temp_thre,min_temp_thre,0,0,0,0,0,0,0,0,0,0,
max_temp_thre,max_temp_thre,0,0,0,0,0,0,0,0,0,0,
min_temp_thre,min_temp_thre],dtype=np.float64)
pattern_tokyo = bedcmm.pattern_1d(np_temp_tokyo,base)
pattern_akankohan = bedcmm.pattern_1d(np_temp_akankohan,base)
hot_continus_hour_tokyo = pattern_tokyo>1
hot_continus_hour_akankohan = pattern_akankohan>1
hot_continus_day_tokyo = [ np.sum(hot_continus_hour_tokyo[i*24:i*24+24])>0 for i in range(int(len(np_temp_tokyo)/24))]
hot_continus_day_akankohan = [ np.sum(hot_continus_hour_akankohan[i*24:i*24+24])>0 for i in range(int(len(np_temp_akankohan)/24))]
print(f"tokyo 12hour pattern cont hot 3 days:{np.sum(hot_continus_day_tokyo)}/{len(hot_continus_day_tokyo)-3}")
print(f"akankohan 12hour pattern cont hot 3 days:{np.sum(hot_continus_day_akankohan)}/{len(hot_continus_day_akankohan)-3}")
tokyo 12hour pattern cont hot 3 days:86/363
akankohan 12hour pattern cont hot 3 days:3/363
結果を見ると、東京の値は同じですが、阿寒湖畔の方は、三日増えてますね。
12時間の間隔なので最低気温でない気温が計算対象になっているので増えた物と思われます。
まとめ
暑い日が続く日がどれだけあるのか、新手法でも計算できた。
最後に
パターン抽出の使い方のイメージが少しでもつけばと思います。
よろしくお願いいたします。
Github
興味があればよろしくお願いいたします。
新手法のGithub
明日の時系列データ Advent Calendarは @okadada
(carp okada) さんの 【第3回】通知で完成:Grafana Alertingで“うるさくない”自分PCアラート設計(Grafana Alerting + Prometheus + (任意でLoki)) です!
