乙Py先生のプログラミング教室
初学者のためのプログラミング学習サイト

予測

今回は現在の成績から
大谷選手の2024シーズン結果を
予測してみました。

解説動画はこちら




はじめに

メジャーリーグ2024年シーズン
大谷選手の現在までの成績(05/25まで)
こちらを使って今シーズンの成績を予測します。



今シーズンの全打席結果が
掲載されているサイトが有ったため
そちらからデータを取得します。

掲載先

こちらによると現時点では
203打数69安打 打率.340
13本塁打 35打点 39得点 13盗塁
という成績でした。


現時点の成績

こちらの結果から分析すると
本塁打:0.05652173913043478
三塁打:0.008695652173913044 
二塁打:0.0782608695652174 
 安打:0.1565217391304348
 三振:0.1826086956521739
 四球:0.10869565217391304
アウト:0.40869565217391307
という確率になりました。

この確率を用いて
シミュレーションを行います。

メジャーリーグの年間平均打席数が650打席
これを1000シーズン行ったという設定です。

import random
import pandas as pd

# バッティング結果の確率を設定
batting_results = {
    "homerun": 0.05652173913043478, # 本塁打
    "triple": 0.008695652173913044, # 三塁打
    "double": 0.0782608695652174,  # 二塁打
    "single": 0.1565217391304348,  # 安打
    "strike": 0.1826086956521739, # 三振
    "walk": 0.10869565217391304, # 四球
    "out":  0.40869565217391307 # その他のアウト
}

def simulate_batting():
    rand = random.random()
    cumulative_probability = 0.0
    for result, probability in batting_results.items():
        cumulative_probability += probability
        if rand < cumulative_probability:
            return result
    return "out"

base = []
for i in range(1000):
    tmp = {k:0 for k in batting_results.keys()}
    n = 650
    for i in range(n):
        s = simulate_batting()
        if s in tmp:
            tmp[s]+=1
        else:
            tmp[s]=1
    base.append(tmp)

df = pd.DataFrame(base)
df["hits"] = df["homerun"] + df["triple"] + df["double"] + df["single"]
df.describe()

ここからホームランと
ヒット数を予測します。
mport pandas as pd
import matplotlib.pyplot as plt
import numpy as np

# homerunの平均値と標準偏差を計算
mean = df['homerun'].mean()
std = df['homerun'].std()
print(f"{int(mean-std)}, {int(mean)}, {int(mean+std)}")

# ヒストグラムを表示
df['homerun'].hist(bins=20, alpha=0.7)

# 平均値、標準偏差±1のラインを描画
plt.axvline(x=mean, color='red', linestyle='--', label='mean')
plt.axvline(x=mean+std, color='green', linestyle='--', label='std+1')
plt.axvline(x=mean-std, color='blue', linestyle='--', label='std-1')

# 凡例を表示
plt.legend()
plt.show()
download-1

# hitsの平均値と標準偏差を計算
mean = df['hits'].mean()
std = df['hits'].std()
print(f"{int(mean-std)}, {int(mean)}, {int(mean+std)}")

# ヒストグラムを表示
df['hits'].hist(bins=20, alpha=0.7)

# 平均値、標準偏差±1のラインを描画
plt.axvline(x=mean, color='red', linestyle='--', label='mean')
plt.axvline(x=mean+std, color='green', linestyle='--', label='std+1')
plt.axvline(x=mean-std, color='blue', linestyle='--', label='std-1')

# 凡例を表示
plt.legend()
plt.show()
download


まとめ
05/25日までのペースだと
ホームラン数 : 36本(±6)
ヒット数 : 195本(±12)
あたりに落ち着く可能性が高いです。

年間40本塁打
200安打は少し、厳しいかもしれませんが
これからの活躍に期待したいですね


きょうはここまでです
それでは。

新型コロナウィルスの感染者増加が止まりません。

このまま行ったらどうなるのかを
データから予測してみました。


解説動画はこちら



さて
今回は予測モデルを使って未来の予測を行います。

用いるライブラリとしては
pandas
matplotlib
fbprophet
になります。

一番初めにデータを読み込んでみましょう。

pandasでデータの提供元(奥村研究所)から
ダウンロードしてデータ化します。
import matplotlib.pyplot as plt
import pandas as pd
%matplotlib inline

df = pd.read_csv("https://oku.edu.mie-u.ac.jp/~okumura/python/data/COVID-19.csv",
                 index_col='Date', parse_dates=['Date'])

これでデータフレームにデータが読み込まれます。

データは4列あるようです。

まずは感染者数の推移を見てみましょう。
df.iloc[0:,0:2].plot(figsize=(16,9))
plt.show()
download

直近での推移が爆裂していますね。
増加率も見てみましょう。
pandasの関数 pct_changeで増加率を算出できます。

df['diff_Global Confirmed'] = df['Global Confirmed'].pct_change()
df['diff_Global Deaths'] = df['Global Deaths'].pct_change()
plt.figure(figsize=(16,9))
plt.bar(df.index,df['diff_Global Confirmed'],alpha=0.3,label="Confirmed")
plt.bar(df.index,df['diff_Global Deaths'],alpha=0.3,label="Deaths")
plt.legend()
plt.show()
download-1

1月末ごろから
中国での大流行があったことが
みて取れます。


中国を抜かした世界の推移を見てみましょう。
別の列を用意してあげます。
df['Confirmed2']=df['Global Confirmed'] - df['China Confirmed']
df['Deaths2']=df['Global Deaths'] - df['China Deaths']
df.iloc[0:,6:8].plot(figsize=(16,9))
plt.show()

download-2

中国以外は3月の頭くらいから
急激に増えているようですね。

増加率も見てみると

df['diff_Confirmed2'] = df['Confirmed2'].pct_change()
df['diff_Deaths2'] = df['Deaths2'].pct_change()
plt.figure(figsize=(16,9))
plt.bar(df.index,df['diff_Confirmed2'],alpha=0.3,label="Confirmed")
plt.bar(df.index,df['diff_Deaths2'],alpha=0.3,label="Deaths")
plt.legend()
plt.show()
download

2月の手前に急激に増えた日がありますね。
ここら辺が起点になっているようです。

次に死亡率です。
df['Death Rate'] = df['Deaths2'] / df['Confirmed2']
plt.figure(figsize=(16,9))
plt.bar(df.index,df['Death Rate'],alpha=0.8,label="Death Rate")
plt.legend()
plt.show()
download-1

直近では5%近くなっていてどんどん上がってきてもいます。

このまま増え続けるとどうなるのか
感染者数の推移を予測してみます。
facebookのprophetを用います。

これはインストールをしないと使えないので
お気をつけください。
from fbprophet import Prophet
import warnings

warnings.simplefilter('ignore',)
model_df = df[['Confirmed2']]
model_df = model_df.reset_index()
model_df = model_df.rename(columns={'Date':'ds','Confirmed2':'y'})
model_df.head()
予測用のデータは
ds,yの2列を用意してあげます。
dsは日付、yは感染者数です。


ds
y
02020-01-204
12020-01-215
22020-01-2310
32020-01-2416
42020-01-2523


モデルを作ります。
model = Prophet()
model.fit(model_df)

最後に予測です。
予測したい日数分の空のデータフレームを用意します。

空のデータフレームを使って
学習したモデルで予測します。
future_df = model.make_future_dataframe(600)
forecast_df = model.predict(future_df)
model.plot(forecast_df)

可視化もできます。
結果は
スクリーンショット 2020-03-29 17.17.04

このままの推移が続くと
今年の終わりには600万人
来年の6月にはその倍くらいにはなっています。

すでに対策を始めていますので
ここまでにはならないと思いたいですが
不要不急の用事がない限りは
あまり出歩かない方が良いでしょうね。

死亡率も5%近くということで
20人のうち一人亡くなると考えると
無視できない確率かなと
個人的には思います。

リモートワークが続いて
ずっと家にいるわけですが

早く
収束してくれることを
願うばかりであります。


はいどうもこんばんは乙pyです。

今日はニコニコ動画さんの
有料会員の推移が気になってしまったので
有料会員数の予測をしてみました。

解説動画はこちら


まずニコニコ動画さんの
最近の有料会員数ですが
決算などで発表されているので
そこからデータ化しました。
年(期) 会員数(万人)
2015-09 253
2015-12 254
2016-03 256
2016-06 256
2016-09 256
2016-12 252
2017-03 243
2017-06 236
2017-09 228
2017-12 214
2018-03 207
2018-06 200
2018-09 194
2018-12 188


さてこれをPythonを使って予測していきます。
最初に必要なライブラリの読み込みです。
from fbprophet import Prophet
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

次の会員数をデータ化します。
データはPandasのデータフレームにします。
df = pd.DataFrame({
    'ds': pd.to_datetime([
        "2015-09-01","2015-12-01","2016-03-01","2016-06-01",
        "2016-09-01","2016-12-01","2017-03-01","2017-06-01",
        "2017-09-01","2017-12-01","2018-03-01","2018-06-01",
        "2018-09-01","2018-12-01"])
    ,'y': [253,254,256,256,256,252,243,236,228,214,207,200,194,188]
} , index=pd.to_datetime([
    "2015-09-01","2015-12-01","2016-03-01","2016-06-01",
    "2016-09-01","2016-12-01","2017-03-01","2017-06-01",
    "2017-09-01","2017-12-01","2018-03-01","2018-06-01",
    "2018-09-01","2018-12-01"
]))
これでデータフレームの完成です。

一旦可視化をして推移を見てみましょう。
plt.figure(figsize=(12, 6))
plt.scatter(df.index, df['y'])
plt.xticks(rotation=70)
plt.show()
nico01

このような会員数の推移ですね。
2015年あたりをピークに
そこからは下降路線をたどっています。

この推移から未来を予測します。

予測にはFacebookの
Propfetというライブラリを用います。

モデルの呼び出しも簡単です。
#モデルの呼び出し
model = Prophet()
学習も1行で終わります。
#学習
model.fit(df)
学習させるにはコツが必要で
時間に該当するものを ts というカラムでTimestampにしておく
数値は y というカラムでデータフレームに定義しておく
必要があります。

ファイルを読み込んでデータフレームを作った際は
カラム名やカラムのデータ型を
Propfet用に合わせる必要があります。

次に予測です。

予測は未来3000日分としました。
このライブラリは日で計算されるようで
引数 periods に日数を入れてあげて
model.make_future_dataframe()という関数を
呼んであげます。

そうすると予測用のデータフレームが作られます。

最後にmodel.predict()で作ったデータフレームで
予測結果のデータフレームを作ります。
#予測
future = model.make_future_dataframe(periods=3000)
forecast = model.predict(future)
たったこれだけで未来予測が終わります。

使える変数は日付と数値だけと
変数が少ないので
簡易な予測にはもってこいのライブラリです。


最後に予測の結果を可視化しましょう。
# 可視化
model.plot(forecast) plt.show()
nico02

日での予測の結果はかなり上下動が激しい感じなので
周期性の方を見てみます。

model.plot_components(forecast)
plt.show()
nico03

はい
これだと綺麗に予測の結果が出ますね。

このままの下降ラインをたどると
2026年には有料会員数が0になるという結果がでました。

下振れが激しければ2024年でも
有料会員数が0になる未来もあり得るという予想結果でした。

あくまでも現状の数値を使っての予測のため
そのままの下降線をたどるということは
少ないかもしれませんが

施策次第では
V字回復もあり得るシナリオではあるので
これからのニコニコ動画さんの
巻き返しに注目したいところです。

頑張れニコ動!!!

このページのトップヘ