異常値?特殊日?の発見と対応方法の検討

異常値?特殊日?の共有

  • 参加者同士が切磋琢磨し、またノウハウ・知識を共有することが目的
  • 異常値?特殊日?を見つけたので対応方法を検討してみましたので、メモになります。
import pandas as pd
pd.options.display.max_columns = 100
pd.options.display.max_rows = 999
pd.options.display.float_format = '{:.6f}'.format
import numpy as np
import math
import warnings
warnings.filterwarnings('ignore')

%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import seaborn as sns

import datetime
import time
from google.colab import drive
drive.mount('/content/drive')
Mounted at /content/drive
path = "/content/drive/MyDrive/tmp/7_probspace/3_taxi/"
train = pd.read_csv(path+'data/train_data.csv', parse_dates=["tpep_pickup_datetime"]).rename(columns={'tpep_pickup_datetime':'ds'})

trainにNullはないが、全ての地点で需要が極端に少ない時間がないかチェック

train_ds = train.set_index("ds").astype(int)
train_ds.loc[train_ds.sum(axis=1)<=100,:]
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
ds
2017-03-12 02:00:00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2017-03-12 02:30:00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 2 0 0 0 0 0 0
2018-03-11 02:00:00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2018-03-11 02:30:00 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2019-03-10 02:00:00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2019-03-10 02:30:00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

前後の時間を見る

train_ds.loc[((train_ds.index >= "2017-03-12 01:00:00")&(train_ds.index <= "2017-03-12 04:00:00")),:]
# 他の時間帯
# train_ds.loc[((train_ds.index >= "2018-03-11 01:00:00")&(train_ds.index <= "2018-03-12 04:00:00")),:]
# train_ds.loc[((train_ds.index >= "2019-03-10 01:00:00")&(train_ds.index <= "2019-03-12 04:00:00")),:]
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
ds
2017-03-12 01:00:00 82 28 23 19 22 10 14 24 17 19 38 315 72 2 8 4 243 22 27 1020 44 19 179 22 101 257 131 425 15 113 11 59 89 3 49 134 130 23 261 24 9 690 33 10 271 166 91 141 249 20 190 7 28 115 2 23 91 6 30 12 128 326 163 57 67 295 53 87 81 165 7 152 419 56 59 7 21 28 181
2017-03-12 01:30:00 78 35 14 15 11 3 4 25 13 13 37 359 53 0 7 0 238 11 28 965 32 28 165 20 72 249 131 419 9 121 7 19 104 2 32 115 102 18 280 7 7 786 23 11 262 92 85 102 223 21 170 6 23 100 2 14 77 8 14 13 113 259 138 70 52 294 47 52 69 96 11 155 420 59 38 3 16 12 132
2017-03-12 02:00:00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2017-03-12 02:30:00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 2 0 0 0 0 0 0
2017-03-12 03:00:00 84 29 15 14 6 5 2 21 10 9 27 330 78 1 12 2 267 18 30 1089 22 26 171 13 107 237 108 407 8 107 17 21 70 1 35 101 68 28 256 11 10 817 22 11 280 67 68 120 243 20 168 4 18 115 2 7 80 6 22 9 115 252 141 89 58 300 43 59 46 95 8 187 403 73 56 7 12 19 160
2017-03-12 03:30:00 123 38 6 12 5 4 2 28 22 6 15 332 98 2 5 4 264 23 17 947 19 11 161 13 73 202 82 383 8 76 18 7 81 1 25 76 39 10 252 12 10 715 23 9 240 58 52 99 231 11 145 6 23 96 3 10 69 21 23 23 109 219 152 77 33 272 29 38 38 66 11 186 356 66 55 7 19 11 116
2017-03-12 04:00:00 88 51 6 10 8 4 4 22 32 8 9 274 115 0 10 0 283 35 26 884 21 15 131 10 63 196 66 268 18 73 17 1 74 2 31 102 26 8 192 13 7 633 13 6 143 36 51 120 210 20 131 6 19 87 0 10 44 18 16 15 89 231 111 63 45 271 21 45 38 57 15 161 278 69 83 11 14 14 114
train_plot = train[("2017-3-10" <= train["ds"])&(train["ds"] < "2017-3-14")]

fig, ax = plt.subplots(79, 1, figsize=(20, 79*4))
for i,obj in enumerate(list(map(str, range(79)))):
    ax[i].plot(train_plot['ds'], train_plot[obj])
    ax[i].axvspan(datetime.datetime(2017, 3, 12, 2, 0), datetime.datetime(2017, 3, 12, 2, 30), color="orange")
    ax[i].set_title(obj)
plt.show()
plt.close()
plt.clf()
# グラフは添付データにて
Output hidden; open in https://colab.research.google.com to view.

ここの対応を検討

  • データ取得元に確認して、何か異常か確認する(今回はできない)
  • Google先生に聞く(外部データの使用申請)

モデル作成時の手法を検討

  • フラグ化する(外部データの使用申請すればOK? 毎年3月の第2日曜日の午前2時)
  • 補間する(予測期間に該当日があれば、手動でゼロ?にする)
  • 無視する(予測期間に該当日があれば、手動でゼロ?にする)
# 補間する場合のサンプルコードをご参考までに
## pandas の interpolate を利用
train_hosei = train.copy()
train_hosei.loc[((train_hosei["ds"]>="2017-03-12 02:00:00")&(train_hosei["ds"]<="2017-03-12 02:30:00")),list(map(str, range(79)))] = float('nan')
train_hosei.loc[((train_hosei["ds"]>="2018-03-11 02:00:00")&(train_hosei["ds"]<="2018-03-11 02:30:00")),list(map(str, range(79)))] = float('nan')
train_hosei.loc[((train_hosei["ds"]>="2019-03-10 02:00:00")&(train_hosei["ds"]<="2019-03-10 02:30:00")),list(map(str, range(79)))] = float('nan')

train_hosei = train_hosei.set_index("ds")
train_hosei = train_hosei.interpolate(method='linear', axis=0)
train_hosei = train_hosei.round().astype(int)

train_hosei = train_hosei.reset_index()
train_hosei[(train_hosei["ds"]>="2019-03-10 01:00:00")&(train_hosei["ds"]<="2019-03-10 04:00:00")]
ds 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
38306 2019-03-10 01:00:00 65 18 8 7 6 1 3 23 6 23 28 232 47 0 3 2 215 17 19 718 24 14 162 8 81 186 108 308 5 48 9 53 86 21 38 89 89 13 148 7 7 472 19 5 232 94 82 78 191 18 122 4 11 115 3 29 102 2 12 9 77 209 121 33 27 172 32 63 29 69 5 85 360 29 24 4 9 17 118
38307 2019-03-10 01:30:00 88 19 3 7 8 2 3 16 14 14 30 187 49 1 4 1 214 14 15 707 12 12 127 4 58 173 112 320 9 44 3 53 77 10 29 89 70 5 161 6 10 594 18 3 254 55 72 80 176 15 81 2 10 108 2 20 76 5 8 7 51 152 102 34 31 172 34 42 27 59 5 95 347 24 32 2 12 9 71
38308 2019-03-10 02:00:00 78 20 2 7 7 3 2 14 13 11 32 188 47 1 5 1 224 15 17 705 15 11 132 5 59 172 104 323 9 58 4 41 79 7 28 84 62 9 162 7 11 594 15 4 227 52 68 81 180 14 86 2 10 99 1 19 76 4 9 7 49 144 98 37 29 170 32 37 28 55 5 111 356 27 32 2 11 11 71
38309 2019-03-10 02:30:00 69 21 2 8 6 3 1 13 11 8 35 189 45 0 5 2 234 17 20 703 17 10 138 7 61 172 95 325 9 71 4 29 81 4 26 78 54 13 164 7 11 593 12 5 201 49 63 82 184 14 90 1 11 89 1 18 76 2 10 8 47 135 93 39 26 167 30 31 28 52 5 127 365 29 31 2 10 13 71
38310 2019-03-10 03:00:00 59 22 1 8 5 4 0 11 10 5 37 190 43 0 6 2 244 18 22 701 20 9 143 8 62 171 87 328 9 85 5 17 83 1 25 73 46 17 165 8 12 593 9 6 174 46 59 83 188 13 95 1 11 80 0 17 76 1 11 8 45 127 89 42 24 165 28 26 29 48 5 143 374 32 31 2 9 15 71
38311 2019-03-10 03:30:00 64 17 4 10 8 5 3 13 6 8 19 216 49 1 6 1 253 17 10 706 8 11 150 2 61 135 71 255 11 52 9 5 73 2 37 74 36 10 132 4 9 551 8 5 91 48 29 85 174 17 87 5 12 67 2 8 43 1 9 8 53 121 76 28 23 122 15 24 23 27 13 127 291 31 37 11 6 11 61
38312 2019-03-10 04:00:00 53 29 2 3 2 3 2 18 6 7 19 247 31 0 5 1 211 16 13 528 19 12 127 5 54 127 65 160 6 36 8 7 57 2 14 51 33 4 113 4 5 441 5 5 60 35 52 75 149 14 80 9 8 70 3 11 32 5 5 4 29 116 71 35 15 125 8 20 12 19 12 119 200 28 30 4 5 16 74

その他の対応方法などございましたら、スキルアップのためにコメント頂けますと、(私は)泣いて喜びます。

# ところで、11月の第1日曜日午前2時は?
display(train_ds.loc[((train_ds.index >= "2017-11-05 01:30:00")&(train_ds.index <= "2017-11-05 03:00:00")),:])
# 直前に増加?
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
ds
2017-11-05 01:30:00 159 52 11 22 8 6 8 39 14 25 43 515 109 1 19 8 511 33 36 1583 64 32 320 29 210 399 195 640 14 125 17 18 200 0 71 153 157 24 337 13 15 1242 35 13 417 165 135 247 444 30 309 17 33 343 0 23 149 4 25 19 140 353 218 86 92 421 58 80 52 109 5 226 660 81 84 14 32 27 172
2017-11-05 02:00:00 48 23 5 15 6 2 1 13 12 5 25 207 57 1 8 2 200 19 23 596 20 10 79 5 73 87 59 242 6 73 6 4 72 0 13 54 28 5 114 3 4 487 12 2 218 22 40 95 151 5 82 1 6 82 2 9 34 2 7 10 47 129 93 39 31 127 15 21 22 27 1 108 239 27 31 8 10 4 62
2017-11-05 02:30:00 28 14 1 19 5 0 4 13 6 8 13 147 52 0 3 0 196 18 11 437 9 4 76 4 66 99 46 181 5 49 8 3 59 0 18 56 24 3 102 9 5 400 9 2 177 27 28 92 111 5 72 2 7 59 1 4 18 7 7 8 51 117 79 34 16 93 17 17 18 18 5 105 223 20 15 8 7 6 50
2017-11-05 03:00:00 23 21 4 6 4 0 6 9 6 6 11 133 33 0 9 0 179 13 6 311 5 10 58 1 61 101 43 128 3 49 8 3 38 2 13 47 15 5 71 9 5 302 4 4 142 28 24 69 112 4 54 2 4 49 1 2 20 3 5 10 35 129 74 21 18 76 6 14 14 23 2 92 158 26 21 5 11 4 38
train_plot = train[("2017-10-28" <= train["ds"])&(train["ds"] < "2017-11-14")]

fig, ax = plt.subplots(79, 1, figsize=(20, 79*4))
for i,obj in enumerate(list(map(str, range(79)))):
    ax[i].plot(train_plot['ds'], train_plot[obj])
    # ax[i].axvspan("2017-11-05 02:00:00", "2017-11-05 03:00:00", color="orange")
    ax[i].axvspan(datetime.datetime(2017, 11, 5, 2), datetime.datetime(2017, 11, 5, 3), color="orange")
    ax[i].set_title(obj)
plt.show()
plt.close()
plt.clf()
# グラフは添付データにて
Output hidden; open in https://colab.research.google.com to view.

添付データ

  • g_1_March_Second_Sunday.png?X-Amz-Expires=10800&X-Amz-Date=20241123T043409Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIP7GCBGMWPMZ42PQ
  • g_2_November_First_Sunday.png?X-Amz-Expires=10800&X-Amz-Date=20241123T043409Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIP7GCBGMWPMZ42PQ
  • Favicon
    new user
    コメントするには 新規登録 もしくは ログイン が必要です。