バスケット分析は、1回の買い物かご(レシート)に何と何が一緒に入っていたかを数え、同時に買われやすい組み合わせを見つける手法です。支持度・信頼度・期待信頼度・リフト値の4指標で組み合わせを評価し、陳列、レコメンド、セット販売の設計に使います。この記事では、アソシエーション分析との関係、4指標の計算、目的設定から効果検証までの手順、ExcelとPythonでの求め方、そして「おむつとビール」がどこまで本当だったのかを扱います。
まとめ:バスケット分析の要点
- バスケット分析は、POSやECの購買履歴にアソシエーションルールの抽出を当てはめたもの。アソシエーション分析が手法の名前で、対象を買い物かごに限ったときの呼び名がバスケット分析。購入の順序まで見るなら別の手法(系列パターンマイニング)になる。
- 評価は支持度(同時購買レシートの割合)→信頼度(Aを含むレシートのうちBも含む割合)→期待信頼度(全レシートにBが含まれる割合)→リフト値(信頼度÷期待信頼度)の順。数える単位は人ではなくレシート(トランザクション)。
- やり方は「目的の指標を決める→トランザクションの単位をそろえる→商品粒度と期間を決める→ルールを選別する→施策の前後を比べる」の5手順。計算より、粒度と期間の決め方で結果が変わる。
- ExcelはCOUNTIFとCOUNTIFSの4つの数式で4指標を出せるが、商品数nに対して組み合わせはn×(n−1)÷2通り(1,000品目で499,500通り)に増える。仮説のあるペアの検算はExcel、全件からの抽出はPythonのmlxtendなどに任せる。
- 売れ筋どうしはリフト値が構造的に伸びない。上限は1÷(2商品の支持度の大きいほう)で、支持度0.7の商品同士なら最大1.43。
- 「おむつとビール」は1992年の分析例として報じられているが、当時の分析報告書は公開されておらず、棚を並べ替えた事実も確認されていない。
バスケット分析とアソシエーション分析の違い
結論から言うと、アソシエーション分析(アソシエーションルールマイニング)が手法の名前で、バスケット分析はその適用先を買い物かごに限定した呼び方です。使うアルゴリズムは同じで、AprioriやFP-Growthで頻出する組み合わせを探します。
原典が「バスケットデータ」と呼んだ対象
アソシエーションルールという枠組みを最初に示したのは、Agrawal・Imieliński・Swamiが1993年のACM SIGMODで発表した「Mining association rules between sets of items in large databases」です。続く1994年のVLDB論文「Fast Algorithms for Mining Association Rules」(Agrawal・Srikant、IBM Almaden研究所)は冒頭で、バーコード技術の進歩により小売業が大量に蓄積できるようになった販売データを the basket data と呼び、その1レコードは取引日と購入商品からなると定義しています。つまり「バスケット」は分析手法ではなくデータの形を指す語でした。日本語で「マーケットバスケット分析」と呼ぶ場合も対象は同じです。
買い物かご以外の適用先と、購入の順序を見る系列パターンとの境界
アソシエーション分析は、1件の記録を項目の集合として表せれば商品以外にも使えます。Webサイトなら同一セッションを1件、閲覧ページを項目とします。診療報酬データの併用薬、製造ラインで同時に出たアラートも同じ形です。これらはバスケット分析とは呼ばず、アソシエーション分析と呼びます。
見落とされやすいのは、アソシエーション分析は「同じかごの中」しか見ない点です。「カメラを買った客が翌月に予備バッテリーを買う」のように、別々の買い物の順序を追いたい場合は系列パターンマイニングを使います。Agrawal・Srikantが1995年のICDEで発表した「Mining Sequential Patterns」は、両者の違いを、同時に買われるものを探す問題は intra-transaction(取引内)のパターン、系列パターンは inter-transaction(取引間)のパターンを扱い、前者のパターンは順序のない商品集合、後者は順序付きの集合の列だと整理しています。顧客ごとの購買順序を調べるには、取引時刻と同じ顧客の取引を結び付ける識別子が必要です。会員IDなどの識別子がなく、取引を顧客別に結び付けられないPOSデータでは、この分析はできません。手法全体の位置づけはデータマイニングとは?意味と主な手法・アルゴリズムの選び方をPython実行例で解説で整理しています。
支持度・信頼度・期待信頼度・リフト値の計算
10件のレシートを例にします。ビールは7件、おむつは7件、総菜は6件、ミルクは4件に含まれ、ビールとおむつが同時に入っているレシートは5件です。この数字から4指標を計算します。
| 指標 | 意味 | 計算式 | ビール→おむつ |
|---|---|---|---|
| 支持度 | 全レシートに占める同時購買レシートの割合 | 同時購買件数 ÷ 全レシート件数 | 5 ÷ 10 = 0.50 |
| 信頼度 | ビールを含むレシートにおむつも含まれる割合 | 同時購買件数 ÷ ビールの購買件数 | 5 ÷ 7 = 0.714 |
| 期待信頼度 | 全レシートにおむつが含まれる割合 | おむつの購買件数 ÷ 全レシート件数 | 7 ÷ 10 = 0.70 |
| リフト値 | 信頼度が期待信頼度の何倍か | 信頼度 ÷ 期待信頼度 | 0.714 ÷ 0.70 = 1.02 |
リフト値1.02は「ビールが入っているレシートでおむつも買われる確率は、全体の平均より2%高いだけ」という意味です。信頼度は71.4%と高く見えますが、おむつ自体が10件中7件に入っている定番商品なので、信頼度の高さは関連の強さを意味しません。この落差が期待信頼度とリフト値を併記する理由です。なお、信頼度はルールの向きを逆にすると分母が変わります。この例では両商品の購買件数が同じため一致しますが、一般にはA→BとB→Aで異なります。リフト値の詳しい計算例と読み違えのパターンはリフト値とは?計算方法と1.0基準の目安・ExcelとPythonでの求め方にまとめています。
最小支持度と抽出ルール件数の関係
ルール抽出では、先に最小支持度を決めて対象の商品集合を絞ります。1994年のApriori論文はこの手順を「最小支持度以上の頻出集合をすべて求める」「その集合から信頼度の条件を満たすルールを作る」の2段階に分けており、支持度を先に決める設計は原典どおりです。先ほどの10件のデータで最小支持度だけを動かすと、リフト値1.0以上のルール件数は次のように変わりました(mlxtend 0.23.4で実行)。
| 最小支持度 | 頻出アイテム集合 | リフト値1.0以上のルール |
|---|---|---|
| 0.5 | 4件 | 2件 |
| 0.3 | 8件 | 4件 |
| 0.2 | 11件 | 8件 |
| 0.1 | 12件 | 8件 |
商品4つでもこの増え方です。実データでも増加幅は商品数や購買分布、ルールの採用条件で変わります。最初から低い値で回さず、施策に使える件数(目安として数十件)に収まる値を上から探すほうが早く終わります。
バスケット分析のやり方:目的設定から効果検証までの5手順
計算は数式4つで済みます。結果を左右するのはその前後の決め方で、次の5手順で進めます。
手順1・2:目的指標とトランザクション単位の設定
最初に「何を増やしたいか」を1つに決めます。客単価を増やすなら併売件数と追加購入額を、新商品の購入を促すならその商品を結論部とするルールの信頼度を、候補選別の基準にするためです。目的が決まらないまま全ルールを並べると、リフト値の高い順に眺めるだけで終わります。
次に1件のトランザクションを定義します。実店舗はレシート番号、ECは注文ID、飲食は伝票番号が基本です。同じ客が同じ日に2回レジを通った場合や、ECで注文を分割した場合を1件にまとめるかどうかは、この段階で決めておきます。返品・取消のレシートと、商品でない行(レジ袋、送料、ポイント値引き)も先に除きます。レジ袋が全レシートの大半に入っていると、レジ袋を含むルールが上位を埋めてしまいます。
手順3:商品の粒度と集計期間の決め方
商品をJANコード単位で扱うと、購買がサイズや味ごとに分散し、最小支持度に届く組み合わせが少なくなります。逆に中分類(「飲料」「日用品」など)まで粗くすると、当たり前の組み合わせしか出てきません。サイズ違い・味違いを統合した「商品グループ」の粒度から始め、出てきたルールが施策に落とせるかで上下に調整します。
期間も同様で、季節商材を含む3か月と、特売週を含む1週間では出るルールが変わります。クリスマスやお中元の週を含めるかは分析前に決め、特売は「特売期間を含めた全体」と「特売を除いた通常期」を分けて出すと、施策に使えるルールと一過性のルールを切り分けられます。
手順4・5:抽出ルールの選別と施策効果の比較
抽出したルールは、最小支持度で足切りしたうえで、リフト値1.0を超えるもの(1.0未満は一緒に買われにくい負の関連)から目的に合う順に並べ、上位から施策の候補にします。このとき、高いリフト値でも同時購買が数件しかないルールは追加データで確かめます。結果をそのまま売場に出さない理由はもう1つあり、関連があっても並べると客が違和感を持つ組み合わせ(食品と殺虫剤など)は採用しません。
施策を打つ前に、何と比べるかを決めます。棚替えなら曜日構成・価格・特売条件をそろえた前後比較、ECのレコメンド枠なら同時期に無作為に出し分けるA/Bテストです。必要なサンプル数と期間の決め方はABテストとは?必要サンプル数の計算コードと検証期間・判定を誤らせる条件で扱っています。比較の設計がないと、ルールが正しかったのか、季節要因で売れただけなのかを区別できません。
Excelでのバスケット分析:COUNTIFSで4指標を出す数式
「この2商品は一緒に売れているのか」を検算するだけなら、Excelで足ります。シートの形は、A列にレシートID、B列以降に商品を並べ、買った商品に1、買っていない商品に0を入れた表です。先ほどの10件ならA2:A11にR01〜R10、B列がビール、C列がおむつ、D列が総菜、E列がミルクになります。
ECの注文明細やPOSの明細は「注文ID・商品」の縦持ちで出てくることが多いので、まず0と1の表に直します。明細を「明細」シートのA列(注文ID)とB列(商品名)に貼り、集計シートのA列に注文IDを重複なく1件ずつ並べ、1行目のB列以降に商品名を置いたうえで、B2に次の式を入れて表全体へコピーします。
=IF(COUNTIFS(明細!$A:$A,$A2,明細!$B:$B,B$1)>0,1,0)
0と1の表ができたら、ビール→おむつの4指標は次の数式で求まります。H列に置いた場合の例で、値はLibreOffice Calc 26.8で再計算して確かめたものです(関数はExcelと同じです)。
| セル | 求める値 | 数式 | 結果 |
|---|---|---|---|
| H2 | 全レシート件数 | =COUNTA(A2:A11) |
10 |
| H3 | ビールの購買件数 | =COUNTIF(B2:B11,1) |
7 |
| H4 | おむつの購買件数 | =COUNTIF(C2:C11,1) |
7 |
| H5 | 同時購買件数 | =COUNTIFS(B2:B11,1,C2:C11,1) |
5 |
| H6 | 支持度 | =H5/H2 |
0.5 |
| H7 | 信頼度 | =H5/H3 |
0.714 |
| H8 | 期待信頼度 | =H4/H2 |
0.7 |
| H9 | リフト値 | =H7/H8 |
1.020 |
分母の取り方には注意が要ります。全レシート件数のCOUNTAは、必ず全行が埋まるレシートID列に当ててください。商品列が「○」と空白で構成されていると、COUNTAは○の件数を返して分母が壊れます。0と1の表なら、対応する行の積を合計する=SUMPRODUCT(B2:B11,C2:C11)でも同時購買件数は同じ5になります。
網羅的な抽出をExcelでやるのは現実的ではありません。2商品の組み合わせ数は商品数nに対してn×(n−1)÷2で増え、100品目で4,950通り、1,000品目で499,500通りになります。3商品の組み合わせまで見るならさらに桁が上がります。Excelは仮説のあるペアの検算、ライブラリは全件からの候補抽出、と役割を分けます。
PythonのmlxtendによるApriori・FP-Growthの実行例
Pythonでは、mlxtendのassociation_rulesで頻出アイテム集合からルールを抽出し、支持度・信頼度・リフト値を一覧にできます。先ほどと同じ10件のサンプルレシートを使い、実行コードと出力を掲載します。使ったバージョンはPython 3.9.6・pandas 2.3.3・mlxtend 0.23.4です。
import pandas as pd
from mlxtend.preprocessing import TransactionEncoder
from mlxtend.frequent_patterns import apriori, association_rules
transactions = [
["ビール", "おむつ", "総菜"], ["ビール", "おむつ"], ["ビール", "総菜"],
["おむつ", "ミルク"], ["ビール", "おむつ", "ミルク"], ["総菜", "ミルク"],
["ビール", "おむつ", "総菜"], ["おむつ", "総菜"], ["ビール", "総菜"],
["ビール", "おむつ", "ミルク"],
]
te = TransactionEncoder()
df = pd.DataFrame(te.fit(transactions).transform(transactions), columns=te.columns_)
freq = apriori(df, min_support=0.2, use_colnames=True)
rules = association_rules(freq, num_itemsets=len(df), metric="lift", min_threshold=1.0)
rules["antecedents"] = rules["antecedents"].apply(lambda s: ",".join(sorted(s)))
rules["consequents"] = rules["consequents"].apply(lambda s: ",".join(sorted(s)))
out = rules[["antecedents", "consequents", "support", "confidence", "lift"]]
out = out.sort_values(["lift", "antecedents", "consequents"], ascending=[False, True, True])
print(out.to_string(index=False, float_format="%.3f"))
antecedents consequents support confidence lift
ビール,ミルク おむつ 0.200 1.000 1.429
おむつ ビール,ミルク 0.200 0.286 1.429
おむつ ミルク 0.300 0.429 1.071
ミルク おむつ 0.300 0.750 1.071
おむつ ビール 0.500 0.714 1.020
ビール おむつ 0.500 0.714 1.020
おむつ,ビール ミルク 0.200 0.400 1.000
ミルク おむつ,ビール 0.200 0.500 1.000
コードで押さえる点は2つです。ひとつは association_rules の第2引数が num_itemsets であること。0.23.2でこの引数が追加されたため、association_rules(freq, "lift", 1.0) のように位置引数で書くと、第2引数の num_itemsets に文字列が渡って失敗します。metricとmin_thresholdはキーワード引数で指定してください。もうひとつは並べ替えです。抽出結果の行順はPythonの文字列ハッシュの影響を受けるため、資料に貼る前に sort_values で並びを固定しないと、実行環境やハッシュシードによって順番が変わる場合があります。
PyPIの最新版は0.25.0(2026年6月6日公開、Python 3.11以上が必要)です。v0.25.0のソースでは association_rules と fpgrowth の引数は0.23.4と同じ並びで、apriori には0.23.4に無い n_jobs 引数が加わっています。上のコードはキーワード引数で書いているので、そのまま動きます。
AprioriとFP-Growthの選択基準
Aprioriは「頻出集合の部分集合は必ず頻出である」という性質(1994年の原典では any subset of a large itemset must be large)を使い、前段で残った集合からのみ候補を作ることで探索を絞ります。ただし候補集合の生成と照合を繰り返すため、商品数が多く長いパターンが出るデータでは負荷が高くなります。
その弱点に対して提案されたのがFP-Growthです。Han・Pei・Yinが2000年のSIGMODで発表した「Mining Frequent Patterns without Candidate Generation」は、データをFP-treeという接頭辞木に圧縮し、候補集合を作らずに頻出パターンを求めます。mlxtendでは from mlxtend.frequent_patterns import fpgrowth を追加し、頻出集合を求める行を freq = fpgrowth(df, min_support=0.2, use_colnames=True) に変えます。この例で指定するキーワード引数は共通ですが、両関数の引数一覧は同一ではありません(apriori は low_memory、fpgrowth は null_values を持つ)。掲載の10件に最小支持度0.2を設定すると、どちらでも同じ11件の頻出アイテム集合が得られます。結果は変わらないので、同じデータと最小支持度で比べ、処理時間やメモリ使用量が改善するならFP-Growthへ替える、という判断で足ります。
「おむつとビール」の分析結果と棚替えの裏付け
バスケット分析の説明でほぼ必ず登場するのが、「若い父親がおむつを買うついでにビールを買うという意外な組み合わせを発見し、隣り合わせに陳列したら両方の売上が伸びた」という話です。この逸話は、分析結果の部分と施策の部分を分けて見る必要があります。
出所は1992年、Thomas BlischokのグループがアメリカのAmerican Stores傘下Osco Drug向けに行った分析です(所属は1998年のComputer Business ReviewがNCR、2006年のThe RegisterがTeradataのグループと書いています)。The Registerの検証記事によれば、対象は約120万件のバスケットで、夕方5時から7時にビールとおむつが一緒に買われる傾向が見つかりました。当時の分析報告書は公開されておらず、以上は報道による説明です。また同記事は、使われたのは当時の「query generation tools」で、年齢や性別との相関は確認されていないとも書いています。1992年はアソシエーションルールの論文(1993年)やApriori(1994年)より前で、「若い父親」という人物像も、データで確かめられたものではありません。
問題は後半です。1998年4月6日のComputer Business Review(現Tech Monitor)はForbesの記事を引いて話の出所を特定したうえで、 it turns out that Osco never did rearrange its shelves to put the beer and diapers together (Oscoはビールとおむつを並べる棚替えを結局行わなかった)と書いています。The Registerも、このチェーンが商品配置を動かして情報を活用した形跡はない(does not appear to have exploited the information by moving the products around)としています。「売上が伸びた」という結末は、一次情報では裏付けられていません。
ここから引き出せる教訓は実務的です。相関が見つかることと、それが棚替えや販促に値することは別の判断だということ。時間帯によって併売傾向が異なる可能性があるため、「ビールとおむつ」という商品名だけで施策を決めず、時間帯別の支持度や信頼度も確認します。ルール一覧から施策を選ぶときは、時間帯・店舗・顧客層といった条件をセットで残してください。
売れ筋商品でリフト値が伸びない理由
売れ筋商品を分析対象から外すかどうかは、リフト値の上限と施策の目的を分けて判断します。理由は計算式から導けます。AとBの同時購買件数は、Aの購買件数もBの購買件数も超えられません。したがってリフト値の上限は1÷(Aの支持度とBの支持度のうち大きいほう)になります。
先ほどの例では、ビールもおむつも支持度0.7なので上限は1÷0.7=1.43です。実測値の1.02はこの天井の範囲内で、どれだけ強く併売されていても1.43を超えることはありません。一方、支持度0.2の商品集合「ビールとミルク」を条件部とする「ビールとミルクを買ったレシートにはおむつも入る」というルールは信頼度1.000・リフト値1.429となり、上限に到達しています。「リフト値1.5以上を採用ラインにする」といった固定閾値を置くと、支持度0.667を超える商品は組み合わせる相手にかかわらず全滅します。これは定番商品を必ず除外する理由ではありません。共通のリフト値閾値では採用されない商品も、併売件数や施策の利益など、手順1で決めた目的に合う基準で評価します。
小売・EC・飲食での使いどころ
実店舗では、抽出したルールを陳列、クロスマーチャンダイジング、セット販売の設計に使います。優先するのは「一緒に買われているのに売場が離れている」組み合わせで、動線の改善に直結します。併売を前提とした価格設計の考え方はクロスセルとアップセルの違い|使い分け・計算式と赤字・違法になる境界で扱っています。
ECでは、ルールをそのままレコメンドの候補に使えるのが強みです。「この商品を買った人はこちらも買っています」という枠は、アソシエーションルールの信頼度順に候補を並べるだけでも作れます。ただしルール数が数千件に膨らむと運用しきれないため、支持度で足切りしてから表示件数を決めます。購買履歴が少ない立ち上げ期のECでは最小支持度を満たす組み合わせが出ないことが多く、その場合は商品属性を使うコンテンツベース方式や、担当者が選ぶ関連商品から始めます。方式ごとの向き不向きはレコメンドエンジンとは?仕組み・種類と導入判断(SaaS/受託開発の選び分け)を分かりやすく解説で比較しており、購買データを使った推薦の仕組みを自社サイトに組み込む場合はAIエンジン開発(レコメンド)の支援範囲も参考になります。
飲食チェーンでは注文伝票がレシートに相当し、サイドメニューやドリンクの組み合わせからセットメニューを設計できます。1伝票に複数人の注文が混ざる業態では、1人分の組み合わせではなく1卓分の組み合わせとして読む点に注意してください。
よくある質問
アソシエーション分析とバスケット分析の違いは何ですか?
アソシエーション分析は「同時に出現する項目の関係を見つける手法」全般を指し、バスケット分析はその対象を購買履歴(買い物かご)に限定した呼び方です。アルゴリズムは同じで、Webの閲覧ログや併用薬に適用する場合はバスケット分析とは呼びません。
バスケット分析の具体例は?
スーパーでパンとジャムが同じレシートに入りやすいと分かれば、隣の棚に置くかセット価格を付けます。ECなら「この商品を買った人はこちらも」の枠、飲食ならセットメニューの組み合わせ決めが典型です。有名な「おむつとビール」は、1992年に約120万件のバスケットから夕方の併売を見つけたと報道で紹介されていますが、当時の分析報告書は公開されておらず、棚替えが行われたという裏付けもありません。
バスケット分析のエクセルでのやり方は?
レシートIDを行、商品を列にした0と1の表を作り、COUNTAで全レシート件数、COUNTIFで各商品の購買件数、COUNTIFSで同時購買件数を数えれば、4指標は割り算で出せます。全組み合わせの網羅には向かないので、仮説のあるペアの検算に使います。
最小支持度はどのくらいに設定すればよいですか?
一律の正解はなく、出てくるルール件数から逆算します。本文で示したように、まず高めの最小支持度で抽出し、候補件数と同時購買件数を確認しながら段階的に下げます。商品数が多いEC向けのデータでは0.001以下にしないとルールが出ないこともありますが、その水準では候補件数が大幅に増える場合があるので、カテゴリ単位に粒度を上げるほうが扱いやすくなります。
ネットショップでもバスケット分析はできますか?
できます。ECの注文明細はレシートと同じ形式なので、注文IDをトランザクション、商品IDをアイテムとして扱えば同じ計算が成立します。1注文あたりの商品点数が少ないショップでは同時購買の支持度が低く、ルールが出にくい場合があります。その場合はカテゴリ単位に粒度を上げるか、会員IDで複数回の注文を追う系列パターンの分析を検討します。カート投入履歴を使う場合は購入済みデータと分けて集計し、同時購入ではなく同時投入の傾向として評価します。