時系列解析ライブラリProphet　公式ドキュメント翻訳10（1日単位ではないデータ編）

Facebookが公開している時系列解析用のライブラリProphetの公式ドキュメントを翻訳していきます。

目次
[1.Prophet公式ドキュメント翻訳（概要＆特徴編)](https://qiita.com/japanesebonobo/items/96868e58d4da42d36807)
[2.Prophet公式ドキュメント翻訳（インストール編)](https://qiita.com/japanesebonobo/items/a7309bc07c59c11bee7b)
[3.Prophet公式ドキュメント翻訳（クイックスタート編）](https://qiita.com/japanesebonobo/items/6f3234adb592f73bafbf)
[4.Prophet公式ドキュメント翻訳（飽和状態の予測編）](https://qiita.com/japanesebonobo/items/9a5a5a13440e90f06f30)
[5.Prophet公式ドキュメント翻訳（トレンドの変化点編）](https://qiita.com/japanesebonobo/items/26cccef8ee9d45006093)
[6.Prophet公式ドキュメント翻訳（周期性・イベント効果・説明変数の追加編）](https://qiita.com/japanesebonobo/items/e674359618a879a49c05)
[7.Prophet公式ドキュメント翻訳（増加し続ける周期性編）](https://qiita.com/japanesebonobo/items/ed02f49ea66eab432af8)
[8.Prophet公式ドキュメント翻訳（誤差の間隔編）](https://qiita.com/japanesebonobo/items/f1acdd4ec1a1d0948553)
[9.Prophet公式ドキュメント翻訳（外れ値編）](https://qiita.com/japanesebonobo/items/4eb36710c689bca80c71)
**10.Prophet公式ドキュメント翻訳（1日単位ではないデータ編）**
[11.Prophet公式ドキュメント翻訳（モデルの診断編）](https://qiita.com/japanesebonobo/items/2266729f849868581011)
[12.Prophet公式ドキュメント翻訳（ヘルプ編）](https://qiita.com/japanesebonobo/items/08f85d74371240568fff)

2018/10/28公開。原文リンクは以下。
・Prophet概要＆特徴：https://facebook.github.io/prophet/
・公式ドキュメント：https://facebook.github.io/prophet/docs/quick_start.html

今回の記事は1日単位ではないデータ編です。
![スクリーンショット (98).png](https://qiita-image-store.s3.amazonaws.com/0/296645/781a22d4-1eb9-0c03-7cb3-e4bbe940724c.png)
#1日単位より短い間隔のデータ
Prophetは`ds`カラムにタイムスタンプデータを格納しデータフレームに渡すことで、1日単位より短い間隔の時系列データについても、予測することができます。タイムスタンプの形式はYYYY-MM-DD HH:MM:SSでなければいけません。[ここ](https://github.com/facebook/prophet/blob/master/examples/example_yosemite_temps.csv)にあるcsvファイルを参考にしてください。1日単位より短い間隔のデータを使う場合、1日単位の周期性が自動的にフィッティングされます。今回はヨセミテ国立公園の毎日の気温を5分単位で分解したデータをProphetでフィッティングしてみましょう。

```R
# R
df <- read.csv('../examples/example_yosemite_temps.csv')
m <- prophet(df, changepoint.prior.scale=0.01)
future <- make_future_dataframe(m, periods = 300, freq = 60 * 60)
fcst <- predict(m, future)
plot(m, fcst)
```

```py
# Python
df = pd.read_csv('../examples/example_yosemite_temps.csv')
m = Prophet(changepoint_prior_scale=0.01).fit(df)
future = m.make_future_dataframe(periods=300, freq='H')
fcst = m.predict(future)
fig = m.plot(fcst)
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/296645/085650e2-b446-7ce0-7556-d146a753c13d.png)
結果のプロットで一日単位の周期性を見ることができます。

```R
# R
prophet_plot_components(m, fcst)
```

```py
# Python
fig = m.plot_components(fcst)
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/296645/2fdf0503-25b0-2fe5-03fb-cc14536a98d4.png)
#断片的なデータ
上で用いたデータが午前12時から午前6時までの気温の観測値しか、入っていなかった場合を想像してください。

```R
# R
df2 <- df %>%
  mutate(ds = as.POSIXct(ds, tz="GMT")) %>%
  filter(as.numeric(format(ds, "%H")) < 6)
m <- prophet(df2)
future <- make_future_dataframe(m, periods = 300, freq = 60 * 60)
fcst <- predict(m, future)
plot(m, fcst)
```

```python
# Python
df2 = df.copy()
df2['ds'] = pd.to_datetime(df2['ds'])
df2 = df2[df2['ds'].dt.hour < 6]
m = Prophet().fit(df2)
future = m.make_future_dataframe(periods=300, freq='H')
fcst = m.predict(future)
fig = m.plot(fcst)
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/296645/cd867a0a-3a08-bca6-8c4c-f92c42215d89.png)
予測結果はあまりよくないようです。先ほどすべての時間帯のデータを使って予測した結果よりも、未来の予測にかなり大きな変動が見られます。ここで問題なのは、Prophetが1日の一部のデータ(午前12時から午前6時)を、丸1日の周期性にあてはめようとしていることです。そのため、1日単位の周期性をあてはめる際に、データにない時間帯は適当にフィッティングしています。これでは予測が成立しているとは到底言えません。解決策は、データが存在する時間帯についてのみ、予測を立てるということです。以下では、そのことを実装するために`future`データフレームに午前12時から午前6時のみのデータを入れるという制約を設けています。

```R
# R
future2 <- future %>% 
  filter(as.numeric(format(ds, "%H")) < 6)
fcst <- predict(m, future2)
plot(m, fcst)
```

```py
# Python
future2 = future.copy()
future2 = future2[future2['ds'].dt.hour < 6]
fcst = m.predict(future2)
fig = m.plot(fcst)
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/296645/010535c0-f124-f350-bf3a-6f1f813e2cdb.png)
他の断片的なデータに対しても、同じやり方を適用することができます。たとえば、時系列データが平日のみを含んでいる場合、週単位の周期性をあてはめることはできないため、平日のみの周期性をあてはめるように指定します。
#月単位のデータ
月単位のデータをProphetのモデルにフィッティングすることもできます。ただProphetでは、モデリングするデータは連続した時系列データであるという前提があります。そのため、月単位のデータをモデルにフィッティングしても、予測結果は日単位のものを返すため、おかしな結果になってしまいます。今回はアメリカの小売り店の売上を10年分予測します。

```R
# R
df <- read.csv('../examples/example_retail_sales.csv')
m <- prophet(df, seasonality.mode = 'multiplicative')
future <- make_future_dataframe(m, periods = 3652)
fcst <- predict(m, future)
plot(m, fcst)
```

```py
# Python
df = pd.read_csv('../examples/example_retail_sales.csv')
m = Prophet(seasonality_mode='multiplicative').fit(df)
future = m.make_future_dataframe(periods=3652)
fcst = m.predict(future)
fig = m.plot(fcst)
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/296645/55e8a8ff-c45e-fd5f-3f8f-ee820b20f54f.png)
ここでは、断片的なデータのトピックで扱ったデータセットと同じ問題が起きています。年単位の周期性にデータをあてはめる際に、それぞれの月の最初の日のデータしかなく、その他の日については予測不能か、過学習になってしまっています。この問題は周期性の不確かな部分についてMCMCサンプリングを行うことで、解決できます。

```R
# R
m <- prophet(df, seasonality.mode = 'multiplicative', mcmc.samples = 300)
fcst <- predict(m, future)
prophet_plot_components(m, fcst)
```

```py
# Python
m = Prophet(seasonality_mode='multiplicative', mcmc_samples=300).fit(df)
fcst = m.predict(future)
fig = m.plot_components(fcst)
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/296645/a57500ce-63e4-4cb0-06d1-afe40723e10b.png)
今回の周期性には毎月1日はデータが存在するため、各月の初めのあたりは誤差の幅が小さくなっています。ただ、1ヶ月の中間あたりの誤差の幅は大きくなっています。Prophetのモデルに月単位のデータをフィッティングする場合は、月単位の予測のみを立ててください。`make_future_dataframe`の`freq`という引数を指定することで予測ができます。

```R
# R
future <- make_future_dataframe(m, periods = 120, freq = 'month')
fcst <- predict(m, future)
plot(m, fcst)
```

```py
# Python
future = m.make_future_dataframe(periods=120, freq='M')
fcst = m.predict(future)
fig = m.plot(fcst)
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/296645/3d11ef43-8190-f74d-e25f-32367a326a06.png)