OEE(設備総合効率)の算出をClaudeで — 停止ログCSVからパレートまで
設備の停止ログと生産実績の2本のCSVから、可動率・性能・品質を分けてOEEを出し、停止原因のパレートまで作る手順。定義の置き方で数字が変わる落とし穴も扱います。
OEE(設備総合効率)は、停止ログと生産実績の2本のCSVがあれば算出できます。Claudeに頼むときの要点は、計算を任せる前に「何を分母にするか」を人間が決めて文章で渡すことです。定義が曖昧なまま集計させると、もっともらしい数字は出ますが、先月の数字とも他ラインの数字とも比べられません。
ここでは、可動率・性能・品質の3指標を別々に出し、計画外停止の原因別パレートまで作る流れを、動かせるスクリプトつきで説明します。
OEEは3つの比の掛け算 — まず定義を決める
OEEは、可動率・性能・品質の3つを掛けた指標です。日本プラントメンテナンス協会が提唱した指標として知られ、計算式は次のとおりです。
OEEを構成する3指標
可動率
実働時間をスケジュール上の時間で割った値です。止まっていた分だけ下がります。
性能
実際の製造速度を、設計上の標準の製造速度で割った値です。遅く回した分だけ下がります。
品質
良品数を、生産を開始した全数で割った値です。不良の分だけ下がります。
OEE = 可動率 × 性能 × 品質。多くの業種で85%程度が目標に掲げられるとされています。3つを別々に出す意味は、数字が低いときに「止まっているのか、遅いのか、不良なのか」を切り分けられる点にあります。
用語は現場や社内資料で揺れます。「稼働率」「性能稼働率」「良品率」と呼ぶ例もありますが、呼び名より先に確かめるのは分母と分子が何かです。依頼文には、呼び名ではなく式を書きます。入退場記録から待ち時間を月次で出す荷待ち時間の集計でも、先に分母を固定してから集計する点は同じです。
決めておくこと
Claudeに渡す前に、次の4点を決めておきます。
| 決めること | 例 | 変わる指標 |
|---|---|---|
| 休憩・計画保全を負荷時間から引くか | 例引く | 変わる指標可動率の分母 |
| 停止とみなす区分 | 例計画外のみ | 変わる指標可動率の分子 |
| 標準サイクルの出どころ | 例設計値(秒/個) | 変わる指標性能 |
| 品質の分母 | 例生産開始数 | 変わる指標品質 |
最後の行は、品質を「全生産数に対する良品数の割合」とする定義に沿っています。出荷数を分母にすると、途中で捨てた分が消えて品質が実態より良く見えます。
用意するCSVは2本
停止ログと生産実績を分けて持たせます。1本にまとめるより、列の意味が混ざらず、Claudeに説明する文章も短くなります。
停止ログ(stops.csv)は、1停止1行です。
設備ID,開始,終了,停止区分,停止原因
L1,2026-09-01 08:10,2026-09-01 08:40,計画外,金型交換遅れ
L1,2026-09-01 10:00,2026-09-01 10:20,計画外,センサー誤検知
L1,2026-09-01 12:00,2026-09-01 12:30,計画内,休憩
L1,2026-09-01 14:00,2026-09-01 14:45,計画外,材料切れ
L1,2026-09-02 09:00,2026-09-02 09:10,計画外,センサー誤検知
L1,2026-09-02 12:00,2026-09-02 12:30,計画内,休憩生産実績(prod.csv)は、1設備1日1行です。標準サイクルは1個あたりの秒数です。
設備ID,日付,生産開始数,良品数,標準サイクル秒
L1,2026-09-01,242,230,75
L1,2026-09-02,260,255,75停止区分の「計画内」「計画外」は、設備側のログに最初から入っているとは限りません。入っていなければ、停止原因の文字列から人が対応表を作ります。この判断はClaudeに推測させず、対応表をCSVかプロンプトで渡します。
Claudeに頼む手順
コード実行とファイル作成が有効なClaudeであれば、CSVをアップロードして分析を頼めます。Free、Pro、Max、Team、Enterpriseのどのプランでもウェブ・デスクトップ・モバイルで使え、Free・Pro・Maxは「設定」の「機能」でコード実行とファイル作成のトグルを入れます。アップロードできるファイルは1つ30MBまでです。ネットワーク設定や扱える形式はファイル作成・編集の解説にあります。
OEE算出の流れ
- 1
定義を文章で渡す
上の表で決めた4点を、式の形でプロンプトに書きます。
- 2
中間値を出させる
日ごとの負荷時間・稼働時間・可動率・性能・品質・OEEを表で出させます。
- 3
1日分を手計算で照合する
ある1日の停止分を足し算して、表の稼働時間と合うかを見ます。
- 4
パレートを作らせる
計画外停止だけを原因別に集計し、累積比率つきで並べさせます。
依頼文の例です。式を先に固定しているところが要点です。
添付の stops.csv(停止ログ)と prod.csv(生産実績)から、設備L1の日別OEEを出してください。
定義は次のとおりです。独自に変えないでください。
- 負荷時間 = 480分 − 計画内停止の合計分
- 稼働時間 = 負荷時間 − 計画外停止の合計分
- 可動率 = 稼働時間 ÷ 負荷時間
- 性能 = 生産開始数 × 標準サイクル秒 ÷ 60 ÷ 稼働時間
- 品質 = 良品数 ÷ 生産開始数
- OEE = 可動率 × 性能 × 品質
出力は、日付ごとに負荷時間・稼働時間・可動率・性能・品質・OEEを並べた表にしてください。
そのあと、計画外停止だけを停止原因別に合計し、停止分の多い順に累積比率つきで並べてください。
計算に使ったPythonコードも見せてください。最後の1行が効きます。コードが見えれば、分母の取り方が依頼どおりかを読んで確かめられます。表の数字だけを受け取ると、定義が守られたかどうかを後から検証できません。
手元で再現できるスクリプト
Claudeが書くコードに近い形を、手元でも動かせるように示します。pandasがあれば、そのまま動きます。
import pandas as pd
SHIFT_MIN = 480 # 1シフトの拘束時間(分)
stops = pd.read_csv("stops.csv", parse_dates=["開始", "終了"])
prod = pd.read_csv("prod.csv", parse_dates=["日付"])
stops["分"] = (stops["終了"] - stops["開始"]).dt.total_seconds() / 60
stops["日付"] = stops["開始"].dt.normalize()
planned = stops[stops["停止区分"] == "計画内"].groupby("日付")["分"].sum()
unplanned = stops[stops["停止区分"] == "計画外"].groupby("日付")["分"].sum()
d = prod.set_index("日付")
d["負荷時間"] = SHIFT_MIN - planned.reindex(d.index, fill_value=0)
d["稼働時間"] = d["負荷時間"] - unplanned.reindex(d.index, fill_value=0)
d["可動率"] = d["稼働時間"] / d["負荷時間"]
d["性能"] = d["生産開始数"] * d["標準サイクル秒"] / 60 / d["稼働時間"]
d["品質"] = d["良品数"] / d["生産開始数"]
d["OEE"] = d["可動率"] * d["性能"] * d["品質"]
print(d[["負荷時間", "稼働時間", "可動率", "性能", "品質", "OEE"]].round(3))
pareto = (stops[stops["停止区分"] == "計画外"]
.groupby("停止原因")["分"].sum()
.sort_values(ascending=False).to_frame("停止分"))
pareto["累積比率"] = (pareto["停止分"].cumsum() / pareto["停止分"].sum()).round(3)
print(pareto)python oee.py上のCSVで実行した結果は、次のとおりです。
| 日付 | 負荷時間(分) | 稼働時間(分) | 可動率 | 性能 | 品質 | OEE |
|---|---|---|---|---|---|---|
| 9月1日 | 負荷時間(分)450 | 稼働時間(分)355 | 可動率0.789 | 性能0.852 | 品質0.950 | OEE0.639 |
| 9月2日 | 負荷時間(分)450 | 稼働時間(分)440 | 可動率0.978 | 性能0.739 | 品質0.981 | OEE0.708 |
9月1日は計画外停止が95分(30+20+45)あり、可動率が下がっています。9月2日は止まらなかった代わりに、性能が0.739と低くなりました。同じOEEの低さでも、手を打つ先は日によって違います。
パレートは次の結果になります。
| 停止原因 | 停止分 | 累積比率 |
|---|---|---|
| 材料切れ | 停止分45 | 累積比率0.429 |
| センサー誤検知 | 停止分30 | 累積比率0.714 |
| 金型交換遅れ | 停止分30 | 累積比率1.000 |
センサー誤検知は2日にまたがる2件(20分と10分)の合計です。1件ずつ見ると小さい停止でも、原因別に束ねると2位に上がる、というのがパレートを作る価値です。
定義違いで数字が変わる落とし穴
同じCSVでも、置き方で数字は動きます。ここが「OEEを出したのに他ラインと比べられない」の主因です。
休憩を停止に含めるかで、可動率が動く
上の例で、休憩の30分を負荷時間から引かず、拘束の480分を分母に置いたとします。9月1日の稼働時間は、休憩と計画外を合わせて125分を引いた355分で変わりません。可動率は355 ÷ 480 = 0.740になり、OEEは0.599です。分母を450分に置いた場合の0.639とは、同じ日の同じ停止ログで4ポイント違います。
どちらが正しいかではなく、ラインや工場をまたいで同じ置き方に揃っているかが問題です。
性能が100%を超えたら標準サイクルを疑う
同じ9月1日で、標準サイクルを75秒でなく90秒にすると、性能は1.023になります。実際の製造速度が標準を上回った、という意味になるため、多くの場合は標準サイクルの設定が実態より遅いことを示します。Claudeが出した表に1を超える性能があれば、コードの誤りよりも先に、標準サイクルの出どころを確認します。
停止ログに載らない短い停止は性能に混ざる
稼働時間は、負荷時間から停止ログの分を引いて求めています。ログに記録されない数秒の停止は、稼働時間に含まれたまま製造数が減るため、性能の低下として現れます。可動率が高いのに性能が低いときは、ログの粒度を疑う余地があります。
日をまたぐ停止は割り当てが変わる
上のスクリプトは、停止を開始時刻の日付に割り当てます。夜勤で24時をまたぐ停止は、全部が開始日に寄ります。夜勤のあるラインでは、日付の代わりに「シフト日」の列を別に持たせ、その列で集計させます。
パレートに休憩を入れると先頭が休憩になる
上のCSVの計画内停止は休憩が2回で、合計60分です。パレートの母数に含めると、最大項目が休憩になり、対策の対象が見えなくなります。パレートは計画外停止だけで作り、計画内停止は負荷時間の側で扱います。
暦時間を分母にした数字はTEEPで、OEEとは別物
OEEはスケジュールされた稼働時間の中での効率です。24時間365日の暦時間を基準にした指標は、TEEP(Total Effective Equipment Performance)と呼ばれ、TEEP = ローディング × OEEで表します。ローディングは、暦上の時間のうち稼働がスケジュールされた時間の割合です。
たとえば週5日・24時間稼働のラインなら、ローディングは(5日×24時間)÷(7日×24時間)で71.4%になります。他社や他工場の「稼働率」と比べるときは、OEEの話なのかTEEPの話なのかを先に確かめます。
APIでコード実行ツールを使う場合
自社のシステムからAPIで同じ処理を回すなら、コード実行ツールを使い、CSVはFiles APIで上げてcontainer_uploadのブロックで参照します。コンテナのPythonは3.11で、pandasとmatplotlibが入っています。外部への通信は無効なので、実行時に追加のパッケージを入れることはできません。メモリは5GiB、CPUは1です。
料金は、ウェブ検索やウェブ取得のツールと併用しない場合、実行時間で別枠に計上されます。1か月あたり組織ごとに1,550時間は無料で、超過分は1コンテナ1時間あたり0.05ドルです。実行時間の最小は5分です。単価の詳細はコード実行ツールの料金の解説にあります。
関連する分析との使い分け
OEEは、ラインの効率を数字で測るための指標です。個々の設備を壊れる前に直す順番を決めたいときは、保全の優先度づけが向いています。手順はCoworkで設備保全の優先度を決める記事にあります。PLCやセンサーのログから異常の前兆を探す場合は、Claude CodeでPLCのログを解析する手順で扱っています。
次にやること
最初の一歩は、1ラインの1週間分で試し、1日分を手計算して表と合わせることです。合ったら、同じ依頼文をラインごとに使い回します。依頼文の定義部分を変えずに運用すれば、月ごとの数字を同じ物差しで並べられます。
設備IDや品番が社外秘なら、L1のような記号に置き換えてから渡します。集計に必要なのは時刻・区分・原因・数量で、固有名詞は要りません。