「部活」が学校から消える前に。36歳体育教師、Python片手に挑むスポーツテックへの挑戦状
部活動 =「悪」なのか?
「勝利至上主義」「体罰」「教員のブラック労働」……。
2020年頃から加速した部活動の地域移行(地域展開)。 現在、「部活動」という言葉にネガティブな印象を持つ人も少なくないと思います。確かに、文科省が進める改革がうまくいけば、子供にも教員にもメリットはあるはずです。
でも、現場にいる私はどうしても考えてしまうのです。 「部活動」って、そんなに悪いものだったっけ? と。
学校の中に唯一ある「好き」な場所
少しだけ、私の話をさせてください。
中学校や高校において、生徒の居場所は大きく分けて3つあります。「学級」「授業」、そして「部活動」です。 この中で、「部活動」だけが、生徒が自分で選んだ「好き」な場所なんです。
クラスでは目立たない子が、部活のコートの中では見違えるようなリーダーシップを発揮する。 授業中は反抗的な生徒が、なぜか部活の顧問の言うことだけは素直に聞く(笑)。そんな光景を何度も見てきました。
私自身、20代の駆け出しの頃、クラス運営がうまくいかずに悩んでいた時期がありました。 そんな私を救ってくれたのは、部活動でキャプテンを務めていた生徒たちでした。 「先生、私がやるよ!」 「俺に任せて」彼らの頑張る背中に、私自身が何度も励まされてきたんです。
部活動が、学校から離れていく。 それは単なる制度変更ではありません。学校の中にあった「好き」という熱量が、遠くへ行ってしまうこと。 そして、教室では輝ききれない生徒の背中を押すチャンスが、私たち教員から失われてしまうこと。
その喪失感と危機感が、私を突き動かしました。 「自分が、学校と地域をつなぐ架け橋にならなければ」と。
36歳、妻と子一人。安定を捨てて「スポーツテック」へ
私は現在36歳。妻と1歳半の子どもがいます。 正直に言えば、この年齢で全くの異業種へ挑戦することに、迷いがないと言えば嘘になります。
実は、私がキャリアに悩み始めたのは4年前のことです。 聞こえはいいですが、まさに「紆余曲折(という名の迷走)」の連続でした。
その間、CSCS(認定ストレングス&コンディショニングスペシャリスト)や簿記3級を取得し、公立中学校を退職して私立高校で働いたりもしました。 そして何より、プライドを捨てて再受験した公立中学校の採用試験に、見事に不合格になりました。
いま、私は正規の教員ではありません。 でも、その「不合格」があったからこそ、今の私があります。 悔しさ、将来への不安、そして「このままでいいのか」という焦り。すべてがごちゃ混ぜになった2025年の夏、私はある決断をします。
「根性」ではなく「Python」で部活を救う
迷走の日々の中で出会ったのが、プログラミング言語『Python』でした。
きっかけはYouTubeで流れてきた某ひろゆき氏のショート動画。「スキルがないならつければいい。おすすめはPython」という言葉に、単純な私は「これだ!」と直感しました。
もちろん、ただの思いつきではありません。 CSCSの研修や現場指導の中で、スポーツテック企業のサービスに触れるたび、「これからの部活動にはテクノロジーが不可欠だ」と痛感していたからです。
現在進められている地域展開も、指導者不足や運営ノウハウの欠如により、2031年の完全移行へのビジョンはまだ不透明です。 人の手だけでは限界がある。ならば、テクノロジーの力でイノベーションを起こすしかない。
体育教師としての「現場感覚」
CSCSとしての「科学的知見」
そして今学んでいる「Python」
この3つを掛け合わせた時、「体育教師×データサイエンス」という、誰もいないポジションで部活動を支えられると確信しました。
これからのロードマップ
Pythonで「根性論」を可視化してみる
実際に私が今学んでいるPythonを使って、こんなことができるというデモンストレーションをしたいと思います。まだコードを自分では書けないので、AIのアシスタントでコーディングをお願いしています。
今回は、スポーツ科学の世界には、怪我のリスクを予測する「ACWR」という指標があります。もし、大会前に急激に練習量を増やすような「根性論的な指導」を行った場合、選手の体に何が起きるのか?
私の現場経験に基づいた架空の練習データを作成し、Pythonでシミュレーションしてみました。(コードは最後に載せます)

上のグラフを見てください。これは、私の指導経験に基づき「大会前に急激に追い込む指導」を行った場合のシミュレーション結果です。
青い線が「ACWR」という怪我のリスクを示す指標です。グラフの中盤、合宿を想定した期間で数値が跳ね上がり、背景が赤くなっているのが分かります。
この赤いゾーンは、スポーツ科学的に見て「怪我のリスクが危険なレベルまで高まっている期間」を意味します。
恐ろしいのは、現場の感覚だけでは「選手たちが頑張っている、いい練習ができている期間」と錯覚してしまいがちなことです。熱意ある指導が、知らぬ間に生徒を危険に晒してしまう。これが「根性論」の正体であり、データが見せてくれる不都合な真実です。
最後に・・・
まだまだコードにエラーがあり、自分で修正する力はありません。しかし、私がPythonを学ぶ理由は、「見えないリスク」を可視化し、指導者が情熱と安全性を両立できる環境を作りたいのです。
このnoteでは、36歳からの「Pythonリスキリングの泥臭い過程」と、そこから見えてくる「部活動の未来(データ分析によるアプローチ)」を発信していきます。
「思い出」や「精神論」だけでなく、「数字」と「技術」で子供たちのスポーツ環境を守りたい。 そんな私の挑戦を、どうか見届けてください。
# 1. 日本語化ライブラリのインストール(Google Colabの場合、最初にこれが必要です)
!pip install japanize-matplotlib
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import japanize_matplotlib # 日本語化ライブラリ
from datetime import datetime, timedelta
# グラフのスタイル設定
sns.set_theme(style="whitegrid")
# japanize_matplotlibを読み込んだ時点でフォント設定は自動で行われます
# ==========================================
# 1. ダミーデータの生成(シナリオ作成)
# ==========================================
np.random.seed(42)
# 期間設定(約3ヶ月分)
periods = 100
dates = pd.date_range(start=datetime(2025, 6, 1), periods=periods)
# ベース負荷
daily_loads = np.maximum(np.random.normal(loc=500, scale=150, size=periods), 50)
# データフレーム作成
df = pd.DataFrame({'Date': dates, 'DailyLoad': daily_loads})
df.set_index('Date', inplace=True)
# 【シナリオ注入】8月上旬に合宿負荷
df.iloc[60:70, 0] = np.maximum(np.random.normal(loc=950, scale=100, size=10), 800)
# 休養日設定
mask_rest = (np.random.rand(periods) < (1/7))
mask_camp = (df.index >= df.index[60]) & (df.index < df.index[70])
df.loc[mask_rest & ~mask_camp, 'DailyLoad'] = 0
# ==========================================
# 2. ACWRの計算
# ==========================================
df['AcuteLoad'] = df['DailyLoad'].rolling(window=7, min_periods=1).mean()
df['ChronicLoad'] = df['DailyLoad'].rolling(window=28, min_periods=1).mean()
df['ACWR'] = df['AcuteLoad'] / df['ChronicLoad']
# プロット用データ(最初の28日を除外)
df_plot = df.iloc[28:].copy()
# ==========================================
# 3. 可視化(リスクの見える化)
# ==========================================
plt.figure(figsize=(14, 7))
# ACWRの推移
plt.plot(df_plot.index, df_plot['ACWR'], label='ACWR推移', color='navy', linewidth=2.5)
# 危険域設定
threshold = 1.5
danger_dates = df_plot.index[df_plot['ACWR'] > threshold]
if len(danger_dates) > 0:
# 連続期間の判定ロジック
diff = np.diff(danger_dates)
# timedeltaの比較を安全に行うため pd.Timedelta を使用
split_indices = np.where(diff > pd.Timedelta(days=1))[0] + 1
spans = np.split(danger_dates, split_indices)
for i, span in enumerate(spans):
label = '危険ゾーン (ACWR > 1.5)' if i == 0 else None
# エラー回避:numpyの日付型をpandasのTimestampに変換してから計算
start_date = pd.Timestamp(span[0])
end_date = pd.Timestamp(span[-1]) + pd.Timedelta(hours=12)
plt.axvspan(start_date, end_date, color='red', alpha=0.3, label=label)
# 閾値ライン
plt.axhline(y=threshold, color='crimson', linestyle='--', linewidth=1.5, label='閾値 (1.5)')
# 装飾
plt.title('【シミュレーション】部活動における負荷急増と怪我リスクの可視化', fontsize=16, fontweight='bold', pad=20)
plt.ylabel('ACWR (Acute:Chronic Workload Ratio)', fontsize=12)
plt.xlabel('日付(2025年)', fontsize=12)
plt.ylim(0.5, 2.0)
plt.grid(True, linestyle='--', alpha=0.7)
plt.legend(loc='upper left', frameon=True, shadow=True)
plt.tight_layout()
plt.show()