商品をすべて同じ頻度で確認するのが難しいとき、ABC分析は管理の優先順位を考える入口になります。選んだ期間の売上や粗利などで商品を並べ、寄与の大きさをA・B・Cに分けます。ただし、分類は発注量の答えではありません。少額でも欠かせない商品や、売上が大きくても在庫費用が重い商品はあります。
30秒で要点
- 「何の金額を、どの期間・商品集合で集計するか」を先に固定します。
- 売上の累積70%と、商品数の70%は違います。境界をまたぐ商品の扱いも必要です。
- 分類後に欠品、調達期間、需要の変動、粗利、保管費用を確認して管理方法を決めます。
ABC分析で決めるのは管理の優先順位
OracleのABC分析ガイドも、利用者が選んだ評価基準に応じて商品の相対的な重要度を分類する方法として説明しています。在庫確認の頻度には、重要性、原価、調達期間、過去の入出庫なども関係します。Oracle「Overview of ABC Analysis」
この考え方を売上データへ適用すると、重点的に調べる商品を絞れます。Aに分類したから安全在庫を必ず増やす、Cだから必ず廃番にする、といった決定まではできません。
表が収まらない場合は、横にスクロールできます
| 項目 | 集計前に記録する内容 | 混ぜると起こること |
|---|---|---|
| 対象 | 店舗、倉庫、商品群、販売開始日の条件 | 異なる役割の商品を同じ基準で順位付けする |
| 期間 | 例として架空の1か月。比較時も日数や季節を確認 | 販促や季節の違いを管理施策の効果と誤認する |
| 評価額 | 返品処理・税の扱いをそろえた売上、または定義した粗利 | 分母と分子の範囲が食い違う |
| 管理の目的 | 棚卸頻度、欠品原因の調査、品揃えの検討など | 分類を作ること自体が目的になる |
粗利率や在庫回転率も有用ですが、商品の金額を足す場合と同じように比率を単純合計しないでください。まず金額によるABCを作り、その横に粗利率や欠品日数を置く方法なら、何を順位付けしたのかが見えます。
5商品で構成比と累積を計算する
以下は計算用の仮想データです。実在する店舗の改善実績ではありません。税抜売上を同じ1か月で集計済み、返品や欠測なし、各SKUは一度だけ登場する前提です。SKUは在庫管理上の商品単位を表します。
全体売上は120,000+80,000+60,000+15,000+5,000=280,000円です。各商品の売上を280,000円で割ると構成比になり、大きい順に足したものが累積構成比です。
表が収まらない場合は、横にスクロールできます
| SKU | 売上(円) | 構成比 | 累積構成比 | 本例の分類 |
|---|---|---|---|---|
| s1 | 120,000 | 42.86% | 42.86% | A |
| s2 | 80,000 | 28.57% | 71.43% | A |
| s3 | 60,000 | 21.43% | 92.86% | B |
| s4 | 15,000 | 5.36% | 98.21% | C |
| s5 | 5,000 | 1.79% | 100.00% | C |
表示は小数第2位で丸めています。表示値を足すと100.01%になる場合があるため、集計や分類は丸める前の金額で行います。
境界をまたぐ商品をどちらへ入れるか
本例では累積70%をAの目安、累積90%をBまでの目安にし、境界へ到達する、または境界を初めて超える商品まで前の区分へ含めます。判定に使うのは、その商品を追加する直前の累積額です。
- s2を追加する直前は42.86%なので、s2までA。Aの売上は200,000円、全体の71.43%です。
- s3を追加する直前は71.43%なので、s3はB。B単独は60,000円、21.43%です。
- s4以降は追加直前が90%以上なのでC。Cは20,000円、7.14%です。
一方、追加後の累積に「70%以下ならA、90%以下ならB」を適用すると、s2はB、s3はCになります。同じ入力でも規則によって違う結果が出ます。片方を黙って使わず、閾値と境界規則をセットで記録してください。Oracleの製品例にも、境界と一致しない場合に最初の超過商品を含める設定が説明されていますが、以下のコードは独自の教材であり、製品機能の再実装ではありません。Oracle「Set Up ABC Information」
Pythonで境界規則を再現する
必要なライブラリはpandasと、次の図を描くためのMatplotlibです。最初のコードを実行してから、同じPythonセッションで図のコードを実行します。ここではSKUが一意、売上が正の整数円である入力に限定します。ゼロ売上、負の返品額、粗利赤字の商品は隠して捨てず、別表で確認してから集計方針を決めてください。
import pandas as pd
df = pd.DataFrame({
"sku": ["s1", "s2", "s3", "s4", "s5"],
"sales": [120000, 80000, 60000, 15000, 5000],
})
if df.empty or df[["sku", "sales"]].isna().any().any():
raise ValueError("empty or missing input")
if not df["sku"].is_unique:
raise ValueError("aggregate to one row per SKU first")
if not pd.api.types.is_integer_dtype(df["sales"]) or (df["sales"] <= 0).any():
raise ValueError("this example requires positive integer yen")
df = df.sort_values(["sales", "sku"], ascending=[False, True]).reset_index(drop=True)
total = sum(int(x) for x in df["sales"])
cumulative = 0
classes, cum_sales = [], []
for value in df["sales"]:
# Compare integer amounts before adding the current SKU.
group = "A" if cumulative * 10 < total * 7 else (
"B" if cumulative * 10 < total * 9 else "C"
)
classes.append(group)
cumulative += int(value)
cum_sales.append(cumulative)
df["ABC"] = classes
df["share"] = df["sales"] / total
df["cum_share"] = pd.Series(cum_sales) / total
print(df.to_string(index=False))
print(df.groupby("ABC")["sales"].sum().to_dict())
分類の期待値はA・A・B・C・C、区分売上はAが200,000円、Bが60,000円、Cが20,000円です。同額のときはSKUの昇順を使います。同額商品が境界をまたぐ場合、この順序は分析上の約束であり、片方の商品が本質的に優れているという意味ではありません。
大きな1商品だけで複数の閾値をまたぐと、この規則では区分が空になることもあります。必ず各区分へ同じ数の商品を入れるコードではありません。運用上すべての区分が必要なら、別の規則を決めて比較してください。
棒グラフと累積曲線を別の軸で描く
import matplotlib.pyplot as plt
fig, axes = plt.subplots(2, 1, figsize=(7.2, 6), sharex=True)
colors = df["ABC"].map({"A": "#246879", "B": "#ba772d", "C": "#91a5b0"})
axes[0].bar(df["sku"], df["share"] * 100, color=colors)
axes[0].set_ylabel("Sales share (%)")
axes[0].set_ylim(0, 100)
axes[1].plot(df["sku"], df["cum_share"] * 100, marker="o", color="#18394a")
for boundary in (70, 90):
axes[1].axhline(boundary, color="gray", linestyle="--")
axes[1].set_ylabel("Cumulative share (%)")
axes[1].set_xlabel("SKU in descending sales order")
axes[1].set_ylim(0, 105)
fig.tight_layout()
plt.show()
棒は一つの商品の寄与、線はそこまでの合計です。線が高いから、その商品の売上自体が大きいと読むことはできません。
分類を発注や棚割りへつなげる条件
表が収まらない場合は、横にスクロールできます
| 分類後に見ること | 検討できる対応 | 先に確認する条件 |
|---|---|---|
| Aの欠品が多い | 発注頻度や欠品原因を優先して調べる | 調達期間、需要変動、代替品、保管余力、資金 |
| Bの需要が安定している | 定期的な発注・棚卸の基準を見直す | 発注単位、供給の安定性、担当者の作業量 |
| Cの保有費用が大きい | 発注単位の縮小、取り寄せ、品揃えを検討する | 併買、戦略性、契約、供給責任、廃番時の影響 |
たとえば架空の店舗で粗利ベースのABCを使うなら、まず返品と売上原価の範囲を統一します。そのうえで一部の商品群だけ管理方法を変え、同じ期間定義の欠品率、在庫回転、廃棄金額、作業時間を比較します。粗利は販売管理費や在庫保有に伴う費用をすべて引いた最終利益ではありません。分類を作っただけで在庫コスト削減が実証されたとは扱いません。
三つの場面で判断を練習する
- 「Aの割合が50%を超えた」。まず分母を聞きます。本例のAは売上では71.43%、商品数では2/5=40%です。売上比率が50%を超えること自体は異常ではありません。管理できる品目数を知りたいならSKU数を見ます。
- Cに戦略商品が入った。分類と例外理由を両方残します。理由、担当者、見直す日を記録し、売上順位だけで廃番にしません。
- 販促期間だけ順位が変わった。通常期と販促期を分け、欠品や販売開始時期も確認します。どちらの需要に合わせて管理したいかを決めてから閾値を見直します。
商品と顧客を分けて分析を進める
顧客の人数をそろえて寄与を比較するならデシル分析、購入の時期・頻度・金額を組み合わせるならRFM分析、併買の関係を見るならアソシエーション分析が次の検討になります。指標の前提や比較方法はデータ・統計の判断ハブから確認できます。