論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説
📚 用語解説
アソシエーションルール
Association Rule
教師なし学習

🔖 キーワード索引

アソシエーション バスケット分析 Apriori 支持度 信頼度 リフト 確信度 レバレッジ 多重比較 FP-Growth 系列パタン 頻出アイテム集合

association rule」は統計データ分析の文脈で扱う重要概念のひとつ。 本ページでは「association rule」を取り巻く中核キーワードを以下にチップで一覧化する。 各キーワードは関連する概念・手法・道具立てを含み、 文献検索や学習計画の起点になる。

association rule統計分析SSDSE-B-2026前提条件適用範囲落とし穴関連手法Python 実装検証方法

これらのキーワードは「association rule の理解 → 適用 → 検証」のプロセスを構成する。 各章で詳しく解説する。

💡 30秒で分かる結論

🍰 まずはやさしく

セットで売れる組み合わせを探す方法です。

意外な商品のつながりを見つけるために使います。

コンビニで一緒に買われやすいお菓子を探すようなものです。

この章ではルールの基本と評価の方法を学びます。

アソシエーションルール ── 条件付き確率に基づく関連ルール

📍 文脈 ── どこで出会うか

🍰 まずはやさしく

ネットショップのオススメ機能のような仕組みです。

データのつながりから便利な提案をするために使います。

スマホで買い物をする時に出る「おすすめ」が例です。

このページでは定義から実装までを順番に解説します。

Amazonの「この商品を買った人はこちらも」、 スーパーの陳列最適化、 クロスセル提案――どれもアソシエーションルールが基礎にあります。

本ページでは「association rule」を扱う。 統計データ分析コンペティション (2026) の教材で、 SSDSE-B-2026 (47 都道府県 × 複数年 × 100 超列) の実データを使った再現可能な学習を目指す。

「association rule」は統計・データサイエンスの体系における重要概念のひとつ。 本ページは「定義・直感・数式・実装・落とし穴・関連手法」の 6 視点で構成され、 各視点は独立して読めるが順序通り読むと体系的な理解が得られる。

🎨 直感で掴む

🍰 まずはやさしく

「Aを買う人はBも買う」という直感的なルールです。

データから意外な組み合わせを発見するために使います。

参考書を買った人が別の教科書も買うような例です。

ここでは具体的な物語や表を使ってイメージを掴みます。

物語①: 「おむつとビール」伝説

1990 年代、 米国大手スーパー Osco Drug がレシートデータ 120 万件を解析した結果、 金曜夕方に紙おむつとビールを同時購入する人が異常に多い と判明したという逸話があります(厳密には伝説要素も含む)。 「赤ちゃんを寝かしつけた後、 父親が今晩の缶ビールも買いにくる」という仮説が立てられ、 二商品の棚を近づけたところ売上が伸びたとされています。

物語②: Amazon の「この商品を買った人はこちらも」

EC サイトのレコメンドエンジンは、 ユーザーの購買履歴を巨大な「バスケット」とみなし、 アソシエーションルールを使って 意外な共起ペア を抽出します。 例: 統計学の入門書を買った人は、 高確率で R 言語の教科書も買う ── これは support 0.02 / confidence 0.4 / lift 6.0 のような数字で評価されます。

バスケット(トランザクション)の構造

TIDパンバター牛乳ビールおむつ
111000
211100
300111
..................

各行が「1 回のレジ通過 = 1 トランザクション」、 各列が「ある商品が含まれていたかの 0/1 ダミー」です。 アソシエーション分析はこの巨大な 0/1 行列から 「A=1 のとき B=1 になりやすい」 という条件付き構造を見つけます。

本ページでの応用: SSDSE-B-2026 都道府県データ

本ページでは商品の代わりに 都道府県の特性 をアイテムとして扱います。 47 都道府県 × {高齢化率 (≥中央値), 人口 (<中央値), 出生率 (≦中央値), 全国人口シェア (<中央値)} を 0/1 ダミー化し、 「高齢化率が高い県は人口も少ない」のようなルールを抽出します。 EC バスケットと同じ枠組みで、 公的統計から地域構造を読み解けます。

📐 定義/数式

🍰 まずはやさしく

ルールの強さを数字で表す計算式のことです。

そのルールが本当に正しいか判断するために使います。

部活の道具をセットで買う人がどれくらいいるか数える例です。

ここでは支持度などの3つの指標について詳しく読みます。

アイテム集合 $A, B \subseteq I$($I$ は全アイテム集合)、 トランザクション集合 $\mathcal{T}$ について、 ルール $A \Rightarrow B$ は次の指標で評価します。

基本 3 指標
$$ \mathrm{Support}(A \Rightarrow B) \;=\; P(A \cap B) \;=\; \frac{|\{t \in \mathcal{T} : A \cup B \subseteq t\}|}{|\mathcal{T}|} $$ $$ \mathrm{Confidence}(A \Rightarrow B) \;=\; P(B \mid A) \;=\; \frac{\mathrm{Support}(A \cap B)}{\mathrm{Support}(A)} $$ $$ \mathrm{Lift}(A \Rightarrow B) \;=\; \frac{P(B \mid A)}{P(B)} \;=\; \frac{\mathrm{Support}(A \cap B)}{\mathrm{Support}(A)\,\mathrm{Support}(B)} $$
補助指標
$$ \mathrm{Conviction}(A \Rightarrow B) \;=\; \frac{1 - P(B)}{1 - P(B \mid A)} $$ $$ \mathrm{Leverage}(A \Rightarrow B) \;=\; P(A \cap B) - P(A)\,P(B) $$ $$ \mathrm{Jaccard}(A, B) \;=\; \frac{|A \cap B|}{|A \cup B|} \;=\; \frac{P(A \cap B)}{P(A) + P(B) - P(A \cap B)} $$
Lift 値解釈具体例
> 1正の関連(共起しやすい)パン → バター (1.33)
= 1独立(情報なし)天候 → 卵
< 1負の関連(相互排他的)紅茶 → 麦茶 (0.6)
※ Confidence は方向性あり ($A \Rightarrow B \neq B \Rightarrow A$)、 Lift は対称 ($A \Rightarrow B$ と $B \Rightarrow A$ で同値)。

🔬 数式を言葉で読み解く

前節の数式は記号が多くて怖く見えますが、 言葉に直すと 「何人中、 何人が、 一緒に買ったか」 という単純な数え上げです。 一つずつ読み解きましょう。

$\mathrm{Support}(A \cap B) = P(A \cap B)$ ── 「同時購入の頻度」
全トランザクション $|\mathcal{T}|$ のうち、 A と B の両方が現れた回数を割っただけ。 頻度の閾値(min_support)以下のルールはここで切り捨て、 計算量を爆発させない。 例: $|\mathcal{T}|=10{,}000$ 件中、 パン+バターが 400 件 → Support = 0.04(4%)。
$\mathrm{Confidence}(A \Rightarrow B) = P(B \mid A)$ ── 「A を買った人のうち B も買う割合」
条件付き確率。 「パンを買った 600 人のうち、 バターも買ったのは 400 人」なら Confidence = 0.67。 方向性がある:パン → バター と バター → パン で値が異なる。 「このルールを信用していいか」のメイン指標。
$\mathrm{Lift}(A \Rightarrow B) = P(B \mid A) / P(B)$ ── 「単独で買う確率と比べて何倍か」
B の人気バイアスを除去した 純粋な共起の強さ。 Lift = 1 なら独立(情報なし)、 Lift > 1 で正の関連。 「人気の卵」のようにそもそも誰でも買うアイテムは Confidence が高くなりやすいが、 Lift で補正される。
$\mathrm{Conviction} = (1 - P(B)) / (1 - P(B \mid A))$ ── 「ルールが破られにくさ」
「A を買ったのに B を買わない」がどれだけ稀かを測る。 Confidence = 1 で分母が 0 → 確信度 ∞。 完璧なルールほど大きい値。
$\mathrm{Leverage} = P(A \cap B) - P(A)P(B)$ ── 「独立を仮定したときからの差分」
期待される共起頻度 $P(A)P(B)$ を引いた残差。 Lift の「比」に対しこちらは「絶対量」。 Lift が大きくても Support が極小なら Leverage は小さい → 頻度と純度のバランス指標

複数指標を併用する理由: Confidence だけ高くてもターゲット顧客が少なければビジネスインパクトはなく、 Lift だけ高くても 偶然の高 Lift(多重比較問題)に騙される。 実務では Support ≥ X% かつ Confidence ≥ Y% かつ Lift ≥ Z の AND 条件でフィルタするのが定番。

🧮 実値で計算してみる

例 1: 古典的なバスケット例(レシート 1,000 枚)

スーパーのレジ集計で次のクロス表が得られたとします。

バター ありバター なし合計
パン あり400200600
パン なし100300400
合計5005001000
Support(パン ∩ バター) = 400 / 1000 = 0.400 Support(パン) = 600 / 1000 = 0.600 Support(バター) = 500 / 1000 = 0.500 Confidence(パン ⇒ バター) = 400 / 600 = 0.667 Lift = 0.667 / 0.500 = 1.333 Leverage = 0.400 - 0.600 × 0.500 = 0.100 Conviction = (1 - 0.500) / (1 - 0.667) = 1.50 Jaccard = 400 / (600 + 500 - 400) = 0.571

→ Lift 1.33 は 「パンを買った人はそうでない人より 33% 余分にバターを買う」 という意味。 Leverage 0.10 は「独立を仮定したときより 100 件多く同時購入が発生」を表します。

例 2: SSDSE-B-2026 都道府県 47 件(高齢化率 × 人口)

公的統計 SSDSE-B-2026 から 47 都道府県の 2023 年データを取り、 A = 高齢化率(65 歳以上人口 / 総人口)が中央値以上B = 総人口が中央値未満とダミー化します(中央値: aging=31.78%、 pop=1,549,000 人)。

B(人口少)¬B(人口多)合計
A(高齢化高)17623
¬A(高齢化低)61824
合計232447
n = 47 県, |A| = 23, |B| = 23, |A ∩ B| = 17 Support = 17 / 47 = 0.362 Confidence(A ⇒ B) = 17 / 23 = 0.739 Lift = 0.739 / (23/47) = 1.510 Leverage = 0.362 - (23/47) × (23/47) = 0.122 Conviction = (1 - 0.489) / (1 - 0.739) = 1.96

→ Lift = 1.51 は 「高齢化率が高い県は、 ランダム抽出より 51% 多く人口少県に該当する」。 Confidence 0.739 は「高齢化高の県のうち約 74% が人口少県」。 地方部の人口減少と高齢化が同時進行している統計的構造が、 たった 2 つのダミー変数の表から読み取れます。

例 3: Lift だけ見ると騙される例

n=10,000、 ある稀少商品 X (Support 0.001) と 別の稀少商品 Y (Support 0.001) が偶然 2 件だけ同時購入。 Support(X∩Y)=0.0002、 Confidence(X⇒Y)=0.2、 Lift=200。 一見強烈なルールに見えるが、 サンプル数が 2 では 偶然 の域を出ません。 必ず Support と組み合わせ閾値で枝刈り する習慣を。

🧮 数値で深掘り ── 47 都道府県の代表 6 ルール

最後にもう一段階深く、 SSDSE-B-2026 から抽出された具体的なルール 6 件を取り上げ、 Support / Confidence / Lift の数字を一つひとつ「人間語」に翻訳する。 抽象的な指標の話を、 47 都道府県という馴染みあるサンプルで体感したい。

代表ルール表 (min_support=0.10, min_lift=1.20)

# ルール Support Confidence Lift 解釈
R1pop_low ⇒ aging_high0.3620.7391.51人口が少ない県は高齢化率も高い。 地方圏で人口減と高齢化が同時進行する典型構造。
R2aging_high ∧ pop_low ⇒ share_small0.3621.0002.04高齢化高かつ人口少の県は、 全国人口シェアも例外なく小さい。 Confidence 1.00 の完全含意で Lift も最大。
R3aging_high ⇒ birth_low0.2980.6091.24高齢化が進む県は出生率(出生数/総人口)も低め。 Lift 1.24 とやや正の連関。
R4pop_low ⇒ birth_low0.2340.4780.98人口の少なさと出生率の低さはほぼ独立(Lift≈0.98<1)。 代表ルール中で唯一 Lift が 1 を下回り、 共起は偶然期待とほぼ同じ。
R5share_small ⇒ aging_high0.3620.7391.51全国人口シェアの小さい県は高齢化率が高い。 share_small は pop_low と同一集合のため R1 と完全一致する。
R6aging_high ⇒ pop_low0.3620.7391.51R1 の逆方向。 Lift は対称で同値だが、 Confidence の意味(どちらを条件に置くか)が変わる点に注意。
📝 より正確な分析(教材補足): 上表の 6 ルールは、 本ページ Python 実装 ①〜⑤ が実在列 A1101(総人口)・A1303(老年人口)・A4101(出生数)から作った 4 ダミー(aging_high / pop_low / birth_low / share_small)に対して算出した検証済みルールから採っている。 SSDSE-B-2026 に存在しない指標(県内総生産・完全失業率など)は使っていない。 Support / Confidence / Lift の値は ②・⑤ の実行結果と一致する(2023 年 47 都道府県で再計算・検証済み)。 注意点: R5 の share_small(人口シェア中央値未満)は pop_low(総人口中央値未満)と数学的に同一の集合になるため、 R5 は R1(0.362 / 0.739 / 1.51)と完全一致する。 また R4「pop_low ⇒ birth_low」は Lift≈0.98<1 で、 人口の少なさと出生率の低さはほぼ独立(正の連関ではない。 実測 2×2 表 11 県 ≒ 独立期待 11.3 県、 χ²≈0・p≈1.0)。 「人口減・少子・高齢の三重苦」のうち統計的に強く結び付くのは 高齢化↔人口減 であり、 出生率低との共起は弱い点に留意する。

R1 / R6 の Support 計算を手で追う(高齢化高 ⇔ 人口少)

最も基本となるルール R1「pop_low ⇒ aging_high」(およびその逆方向 R6)を例に、 47 都道府県の生データから Support / Confidence / Lift がどう計算されるかを手で追ってみる。 使うのは実在列 A1101(総人口)と A1303(老年人口)から作った 2 ダミーだけ。

前提(実在列 A1101・A1303 の中央値で 2 値化): - 全 47 都道府県 - aging_high (高齢化率 ≥ 中央値): 23 県 - pop_low (総人口 < 中央値): 23 県 - aging_high ∧ pop_low: 17 県 Support(aging_high ∧ pop_low) = 17 / 47 = 0.362 Confidence(aging_high ⇒ pop_low) = 17 / 23 = 0.739 P(pop_low) = 23 / 47 = 0.489 Lift = 0.739 / 0.489 = 1.51 期待件数 (独立仮定): 23 × 0.489 = 11.2 件 実際の件数: 17 件 → 期待より 5.8 件多い ── 偶然の 1.51 倍頻発している

この計算で重要なのは「独立なら何件起きるはずか」を出して、 実際の件数と比べているところ。 Lift はこの比率そのもの。 47 県という小規模サンプルでも、 この共起は χ² 検定で χ²=9.37・p=0.0022(本ページ Python ④ の出力)と有意になり、 偶然ではない構造だと確認できる。

R4 だけが Lift が低い理由

代表 6 ルールの中で R4「pop_low ⇒ birth_low」だけが Lift≈0.98 と 唯一 1 を下回る。 これは何を意味するか? 人口が少ない県と出生率が低い県の共起は偶然期待とほぼ同じ(独立)で、 正の連関はない。 R2(Lift 2.04)や R5(1.51)のように明確に共起する組み合わせとは対照的で、 「人口が少ない ⇒ 出生率も低い」という直感は 2023 年データでは支持されない。

具体的に: 人口が中央値未満の県は 23 件、 そのうち出生率も中央値未満は 15 件。 もし独立なら 23 × (23/47) = 11.3 件のはずなので、 実際は +3.7 件多い。 これは「人口減の県は出生数も細る」傾向を反映しているが、 沖縄のように人口が中位でも出生率が高い県などの例外が混じるため Lift が伸びない。 こうした「例外が分布を引き下げる」現象も、 Lift の数字だけ追っていると見落とす。

χ² 検定で「偶然でない共起」を裏づける

Lift の大小だけでは「その共起が統計的に偶然でないか」は判定できない。 そこで各ルールの 2×2 分割表に χ² 検定をかける。 検証済みの R1/R6(aging_high ⇔ pop_low)を例にとると:

2×2 分割表(本ページ Python ④ の出力): pop_low=0 pop_low=1 aging_high=0 18 6 aging_high=1 6 17 χ² = 9.37, 自由度 = 1, p = 0.0022 (p < 0.01) → 独立仮説は強く棄却。 Lift 1.51 の共起は偶然ではない。

一般に Lift が 1 から離れるほど χ² も大きくなり p 値は小さくなるが、 両者は別の尺度である。 Lift が 1.3 程度の弱いルール(R4 など)は、 47 県という小標本では χ² 検定で有意水準に届かないこともある。 だから「Lift だけでなく χ² も併記」して、 統計的な裏づけの有無を明示する習慣をつけたい。

Bonferroni 補正 ── 多重検定の罠

ダミー変数を増やして数百〜数千のルールを一斉に χ² 検定にかけ、 p < 0.05 のものを「有意」として採用すると、 N 件のルールに対しおよそ N × 0.05 件が偶然に有意判定されて紛れ込む。 Bonferroni 補正では p の閾値を 0.05/N まで厳しくして、 全体(ファミリー単位)での偽陽性率を 5% 以下に抑える。 これを適用すると弱い共起のルールははじき出され、 Lift も χ² も大きい強いルールだけが「真に有意」として残る。 安全側に倒すなら必須の処理。

🏭 業界別応用パターン ── 6 業界 24 ユースケース

アソシエーションルール分析は「バスケット分析」のイメージが強いが、 実は 6 つの業界で全く違う形で使われている。 ここでは各業界の代表的なユースケース 4 件ずつ、 計 24 件を一覧化する。 自分の業務に近い行を探して「何を item 化すべきか」のヒントにして欲しい。

業界 ユースケース トランザクション アイテム 期待される発見
小売 棚配置最適化レシート 1 枚商品 SKU共起率の高い商品を近接配置
クロスセル推薦注文 1 件カテゴリバンドル販売の組み合わせ
廃番判断月間売上商品 + 顧客属性特定属性に依存する商品
来店時刻×商品レシート+時刻商品+時間帯朝コーヒー × パン などの組合せ
医療 併用薬リスク処方箋 1 枚薬剤コード相互作用のある併用パターン
合併症パターン入院 1 回ICD-10 病名同時診断されやすい疾患の組
検査値異常組合せ受診 1 回検査値(区間化)特定疾患を示唆する複合異常
副作用報告FAERS 1 件薬剤 + 副作用既知+未知の副作用シグナル
Web 回遊パス分析セッション 1 回閲覧ページCV につながる回遊パターン
CV ファネル改善ユーザー単位行動イベントCV 前のキーアクション
検索クエリ共起セッション内検索群検索語関連語提案・拡張
広告クリック傾向セッションクリック広告 ID効果的なバナーセット
金融 不正取引検知取引 1 件特徴量(区間化)高 Lift の組合せ=不正パターン
商品クロスセル顧客 1 人保有商品保険+投信などの組合せ
解約予兆顧客 1 人+月取引行動解約前の行動パターン
ポートフォリオ分析投資家 1 人保有銘柄同時保有されやすい銘柄群
公共統計 地域類型化都道府県 1 件指標(区間化)類似指標の地域グループ
政策評価市区町村×年政策+アウトカム政策と成果の共起傾向
災害脆弱性地区 1 件物理+社会指標複合的脆弱性パターン
人口動態国勢調査メッシュ年齢×職業移動が起きやすい属性組合せ
製造 不良連鎖検知製品 1 個検査項目同時に不良になる項目組
設備故障パターン設備×時間窓センサーアラート故障前の共起アラート
サプライチェーン発注 1 件部品コード一緒に注文される部品セット
品質特性連動ロット 1 件工程パラメータ品質と相関するパラメータ組

24 件を眺めると、 「トランザクションをどう定義するか」と「アイテムをどう設計するか」が業界ごとにまったく違うことが分かる。 これがアソシエーションルール分析の汎用性と、 同時に難しさの源泉。 ライブラリは Apriori / FP-Growth で共通化できても、 「何を行と列にするか」の設計は業務知識が握っている。

🛠 ライブラリ比較 ── Python / R / Java の実装選び

アソシエーションルール分析は古典手法だけに、 複数言語で複数のライブラリが乱立している。 実装を選ぶときの目安として、 主要な 7 ライブラリを「対応アルゴリズム」「速度」「可視化」「ドキュメント」の 4 軸で比較する。

言語 ライブラリ 対応アルゴリズム 速度 可視化 使い分け
PythonmlxtendApriori, FP-Growthなし(自作)学習・小〜中規模・教育用途の定番
PythonPyCaretApriori 内包基本グラフ内蔵AutoML パイプラインに組み込みたいとき
Pythonefficient-aprioriApriori 最適化版なし数百万トランザクション向け
RarulesApriori, EclatarulesViz 連携研究・統計分析・可視化重視
RarulesSequences系列パターン基本時系列イベント分析
JavaSPMF160+ アルゴリズムCLI のみ最新アルゴリズム検証・ベンチマーク
Scala/SparkMLlib FP-GrowthFP-Growth 分散版最高外部連携10億トランザクション以上

教育用途や小〜中規模分析なら mlxtend、 統計検定や高度な可視化が必要なら arules + arulesViz、 100 万件超の本番運用なら Spark MLlib FP-Growth、 最新研究を試したいなら SPMF ── という選び方が無難。 本サイトでは教育目的から mlxtend を採用しているが、 同じ結果が R でも再現できるはず。

パフォーマンス目安表

トランザクション数 アイテム種類 推奨実装 想定時間
〜1万〜100mlxtend Apriori数秒
10万数千mlxtend FP-Growth数十秒
100万〜1万efficient-apriori / arules数分
1000万〜数万Spark MLlib十数分〜時間

「いまの mlxtend が遅くなった」と感じたらまず FP-Growth に切り替え、 それでもダメなら efficient-apriori、 さらにダメなら Spark へ移行する流れが定石。 ただし移行には時間とコストがかかるので、 最初から十分なスケーラビリティを見越して設計したい。

❓ 追加 FAQ ── 実務でよく聞かれる 6 問

本文中の FAQ では基本 5 問を扱ったが、 ワークショップ等で初学者から繰り返し質問される 6 問を追加で整理する。

Q6. ルール数が多すぎて読み切れない。 まず何を見るべき?

最初に「Support × Lift × χ² の p 値」の 3 点で機械的に絞り込み(例: Support > 0.05、 Lift > 1.3、 p < 0.01)、 残ったルールを Lift 降順で並べる。 上位 20 件だけを目視で確認し、 業務知識で残すかを判断する。 全件読もうとしない。

Q7. 同じデータでも実装によって結果が違うのはなぜ?

主な原因は (1) min_support の閾値の解釈差(相対値か絶対件数か)、 (2) アイテム集合の最小サイズの違い、 (3) Confidence のカウント方法(双方向で重複出力するか否か)、 (4) 浮動小数の丸め誤差。 同じ閾値設定なのに違う場合はドキュメントを必ず確認。

Q8. ルールを A/B テストで検証する具体的な手順は?

(1) 候補ルール「X⇒Y」を抽出 → (2) ランダムに割り当てた A 群には X の購入時に Y をレコメンド、 B 群には何もしない → (3) 一定期間後、 両群の Y 購入率を比較 → (4) z 検定か Bayesian A/B test で差を検証 → (5) 効果量と CI を報告。 ルールがデータマイニング由来でも、 介入の効果は実験で確認する原則は変わらない。

Q9. ルールが時間で変わってしまう。 どう運用する?

月次か四半期で再抽出し、 Support と Lift の変化を時系列で追う。 Support が半減した/Lift が 1 を下回ったルールは「死んだ」と判断して入れ替える。 「ルールのライフサイクル管理」を最初から運用設計に組み込む。

Q10. 説明変数が多いとき(数千次元)はどうする?

まず PCA や階層クラスタリングで「似たアイテム」をグループ化し、 グループ単位のアソシエーション分析を行う。 全 SKU を直接放り込むと候補集合が爆発する。 また min_support を高め(0.05 以上)に取って大物だけを残す。

Q11. 経営層に説明するとき何を見せれば伝わる?

数式や Lift の話は最小限にして、 (1) 1 行のルール例(「商品 A を買った人は 9 割が商品 B も買う」)、 (2) ルールを使った施策の予想売上効果(「年間 +XX 万円」)、 (3) A/B テストの結果(「対照群比 +X%」)の 3 点に絞る。 統計指標を全部出すと「で、 結局何ができたの?」になりがち。

📌 学習のしめくくり ── 次の一歩

ここまで読み進めたら、 アソシエーションルール分析の基礎・応用・落とし穴は一通り把握できているはず。 次の学習ステップとして、 以下の 4 つの方向に進むのが効果的。

  1. 系列パターンへの拡張: 時間順序付きデータに対する PrefixSpan や SPADE。 「A を買った後 1 ヶ月以内に B を買う」という時間軸を含む知識発見。
  2. グラフマイニングへの拡張: gSpan や CloseGraph で、 SNS のフォロー関係や分子構造から頻出部分グラフを抽出する。 アイテム集合の自然な一般化。
  3. 因果推論との接続: アソシエーションが見つけた共起から、 介入実験や Causal Forest で因果関係を確かめる。 相関と因果のギャップを埋めるためのキャリブレーション。
  4. Embedding ベースのレコメンド: アソシエーションルールは「明示的なルール」を出すが、 word2vec ベースの item2vec ではブラックボックスな類似度で大規模に推薦できる。 解釈性 vs 性能のトレードオフを意識して使い分ける。

最終的に、 アソシエーションルール分析は「機械が見つけた仮説の山を、 人間が業務知識と統計検定で絞り込む」協働プロセス。 全自動で施策まで決められる手法ではないが、 仮説生成器としては今でも一級品。 業務側との対話のきっかけとして使うのが正しい。

本サイトでは引き続き、 Apriori, Lift, バスケット分析 などの関連トピックで深掘りを続けて欲しい。 また、 SSDSE-B-2026 を使った相関分析(相関係数)と比較すると、 同じデータから違う知見が出ることに気づくはず ── アソシエーションは「カテゴリ的共起」、 相関は「連続的共変動」を測る、 という補完関係を体感できる。

📰 古典論文と主要参考文献

🎯 補講: 現場で効くアソシエーションルール 5 原則

アソシエーションルールは「同時購入の発見」だけでなく、 メニュー設計・棚配置・キャンペーン計画など実務の意思決定を支える。 以下の 5 原則は、 SSDSE-B-2026 や POS データを使った教育現場・現場運用で繰り返し効いた知見である。

  1. 支持度・確信度・リフトを必ずセットで見る: 確信度 80% でも支持度 0.001% なら稀少パターン。 リフト 1 未満は逆相関 (一緒には買わない) を示す逆方向シグナル。
  2. 最小支持度はデータ密度で動かす: 売れ筋商品の多い小売は 0.5% 以上、 ロングテール商品中心の EC は 0.05% 程度。 一律値での運用は失敗の元。
  3. 連続値は離散化してから投入: 年齢 25 歳→「20 代」、 購入額 5,432 円→「中額帯 (3,000-6,000 円)」など事前にビン分け。 連続値のまま入れるとルールが爆発する。
  4. 季節性・販促効果と切り分ける: 「ビール × おでん」は冬限定。 「水着 × 日焼け止め」は夏限定。 全期間で 1 本のルールを作るのではなく、 期間ウィンドウを切って抽出する。
  5. 「面白い」を rule-mining 後の人手で再評価: lift が高くても「同じカテゴリ商品同士なので当たり前」というルールが大半。 ドメイン専門家が surprising な少数ルールに絞り込む工程を必ず挟む。

この 5 原則を守れば、 「ルールは出たけど打ち手にならない」という典型的失敗 (lift 過信、 支持度過小、 季節性無視) を避けられる。 SSDSE-B-2026 都道府県データで「人口規模 × 産業構造 × 観光客数」のクロスを切り出すと、 観光業依存県の特徴的バスケットが浮かび上がる。 教育現場では、 まず 3 変数 × 3 ビンの単純な設定から始めて、 学習者にルール解釈を体験させると効果的である。

🎯 補講: 実務適用と教育的活用

本概念は、 SSDSE-B-2026 都道府県データのような実データを扱うあらゆる場面で重要な役割を果たす。 統計分析・機械学習モデリング・ビジネス意思決定のすべての段階で、 本概念の理解度がアウトカムの質を決定づける。 教育現場での活用としては、 まず基本定義を踏まえた上で、 SSDSE データを使った具体的演習を通じて概念を定着させ、 次に発展的応用課題で深掘りするカリキュラム設計が効果的である。 学習者は単に公式を覚えるのではなく、 「なぜこの概念が必要か」「どのような場面で誤用が起きるか」「どう他の概念と接続するか」を体系的に理解することが求められる。

実務適用においては、 ドメイン専門家との密な連携が成功の鍵となる。 本概念を技術者だけで運用すると、 ビジネス価値とのギャップが生じやすい。 定期的なレビュー、 結果の可視化、 ステークホルダーとの対話を通じて、 概念の適用が実際の意思決定改善につながっているかを継続的に検証することが重要である。 また、 関連用語・派生手法との位置関係を明確にし、 過去の文脈・現代の応用・将来の発展形を一連の知識体系として捉えることで、 本概念の真価が発揮される。

🔎 補足: support / confidence / lift の現場での選び方

アソシエーションルールマイニング (Apriori, FP-Growth) では膨大なルールが生成される。 ルールを「使える順」に並べ替えるための主要指標 3 つを、 SSDSE-B 都道府県データの「特定の人口・産業構成パターン」に当てはめて読み直す。

1. support (支持度)

ルール A ⇒ B における trans (A ∧ B) の総 trans に対する割合。 つまり「データ全体で A も B も同時に観察された頻度」。 SSDSE-B-2026 で「人口 100 万未満 ⇒ 高齢化率 30% 超」というルールを考えると、 47 都道府県のうち何件が両方に該当するかを 47 で割った値が support になる。 一般に support が低すぎるルール (例: 0.01 未満) はノイズの可能性が高く、 まず support の閾値で粗くフィルタする。

2. confidence (確信度)

P(B | A) = trans (A ∧ B) / trans (A)。 「A が起きたとき、 どれだけの割合で B も起きるか」を示す。 SSDSE で「人口 100 万未満 ⇒ 高齢化率 30% 超」が confidence 0.85 なら、 「人口 100 万未満の県の 85% は高齢化率 30% 超」と読める。 ただし B が極めて頻出するなら confidence は自動的に高くなるので、 単独では誤判定する。

3. lift (リフト)

P(B | A) / P(B)。 1 を超えれば A の発生で B の発生確率が押し上げられている (正の関連)、 1 未満なら抑制方向、 1 ちょうどなら独立。 lift は「B 単独の発生確率」を base line に置くので、 confidence が見落とすケースを救う指標。 SSDSE-B-2026 で B = 高齢化率 30% 超の base rate を 0.55 とすると、 上のルールの lift = 0.85 / 0.55 ≈ 1.55 で、 「人口 100 万未満を見ると高齢化率 30% 超が 1.55 倍効きやすい」と解釈できる。

3 指標の落とし穴

SSDSE-B-2026 での実用例

カテゴライズして trans を組み立てれば、 都道府県データでも association mining が成立する。 たとえば「人口階級 (S/M/L)」「産業構成 (第 1 次・2 次・3 次の最大シェア)」「高齢化率階級」を各都道府県のフラグ集合とし、 47 trans の market basket に見立てると、 「第 1 次産業優位 ⇒ 高齢化率 35% 超 (conf 0.8, lift 1.6)」のようなルールが取れる。 単純な相関係数では拾えない条件付きパターンを発見するのが利点。

実装時の Tips

🔎 拡張補足: アソシエーションルールの応用と現代的拡張

1. リコメンダーシステムへの応用

Amazon, Netflix, YouTube などの「これも買っています/見ています」推薦は、 アソシエーションルールマイニング (ARM) の代表的応用。 (1) 協調フィルタリング (Collaborative Filtering) は 1995 GroupLens の発展系、 (2) Item-based (Sarwar 2001) はユーザー類似度より計算効率的、 (3) Matrix Factorization (Netflix Prize 2006-2009) で精度向上、 (4) 近年は Neural Collaborative Filtering で深層学習統合。 ARM は説明可能性が高く、 NCF はスケール性が高い、 という両極端を補完的に使う。

2. Sequential Pattern Mining (順序付きアソシエーション)

通常の ARM は集合演算 (A, B が同時に発生) だが、 順序を考慮する Sequential Pattern Mining: GSP, PrefixSpan, SPADE。 例: 「ノート PC を購入 → 30 日以内に外付け HDD」「映画 X を視聴 → 続編 Y を視聴」のような順序関係。 SSDSE-B-2026 は時系列がないが、 仮想的に「2020 年人口減少県 → 2026 年高齢化県」のような時系列 ARM を考察可能。

3. 高次元データでの ARM

Apriori は支持度の単調性で剪定するが、 高次元 (10,000+ アイテム) では候補爆発。 FP-Growth (Han 2000) は FP-tree で線形時間に近い性能、 RElim (Borgelt 2005)、 LCM (Uno 2004) が高速。 大規模 e-commerce では Apache Spark の MLlib FPGrowth が標準。 SSDSE-B-2026 の 47 都道府県 × 100 指標規模では Apriori で十分。

4. ストリーミングデータでの ARM

無限に流入するイベントストリームから「最近のホット」ルールを発見する必要がある場合、 (1) Sliding Window: 過去 N 分のルール、 (2) Damped Window: 時間減衰、 (3) Landmark: 固定起点。 Lossy Counting, Sticky Sampling などの近似アルゴリズム。 リアルタイム異常検知、 IoT センサー連携、 不正検知などで応用。

5. 制約付きアソシエーションルール

(1) Anti-monotonic 制約: 価格が一定以下、 (2) Monotonic 制約: 利益が一定以上、 (3) Succinct 制約: 特定カテゴリ含む、 (4) Convertible 制約: 数学変換で扱える。 SSDSE-B-2026 で「人口減少率 5% 以上の県のみ」のような制約付き ARM が可能。

6. ARM とグラフマイニング

ソーシャルネットワーク、 引用ネットワーク、 知識グラフでの「頻出部分グラフマイニング」は ARM の拡張。 gSpan (2002), Gaston (2004), MoSS。 「同じ研究テーマの研究者は同じ大学に所属」「同じ趣味の人は同じ地域に住む」のようなパターン発見。

7. ARM の評価指標 (リフトを超えて)

support, confidence, lift に加えて: (1) Leverage = P(A ∩ B) - P(A) × P(B)、 (2) Conviction = P(A) × P(¬B) / P(A ∩ ¬B)、 (3) Jaccard = |A ∩ B| / |A ∪ B|、 (4) Cosine = P(A ∩ B) / √(P(A) × P(B))、 (5) Phi = (P(A ∩ B) - P(A)P(B)) / √(P(A)P(B)P(¬A)P(¬B))。 タスクと文脈に応じて選ぶ。

8. 因果アソシエーションマイニング

通常 ARM は相関ベースだが、 因果アソシエーション (Cooper 1997, Spirtes 2000) は do-calculus で因果効果を推定。 「政策 A を実施した県 → 5 年後の人口維持」のような因果関係を観察データから推定する手法。 SSDSE-B-2026 で「DX 投資と労働生産性」の因果関係を ARM + IV (操作変数) で分析可能。

9. ARM の Python 実装

(1) mlxtend は教育的、 Apriori, FP-Growth, Association Rule mining の標準実装、 (2) efficient-apriori はメモリ効率、 (3) pyECLAT は ECLAT アルゴリズム、 (4) Apache Spark MLlib は分散処理。 SSDSE-B-2026 で都道府県を「basket」、 各指標を「item」として ARM 実行可能。

10. SSDSE-B-2026 を題材にしたアソシエーション分析実例

「都道府県 = basket、 (i) 人口減少率 5% 以上、 (ii) 高齢化率 35% 以上、 (iii) 第 1 次産業優位 = item」として ARM を実行。 例えば「(i, ii) → (iii) は support=0.15, confidence=0.85, lift=1.7」と読み取れる。 ベン図と組み合わせて 47 都道府県の構造を視覚化。 教育教材として極めて有効。

11. ARM と説明可能 AI (XAI)

ARM ルールは「IF A THEN B (support, confidence, lift)」と明示的なので、 XAI の代表的な手法の一つ。 (1) Decision Tree ルール抽出、 (2) RuleFit (Friedman 2008)、 (3) Anchors (Ribeiro 2018) などの XAI 手法は ARM と概念的に類似。 ブラックボックス AI (深層学習) を ARM で近似することで、 「なぜそう判断したか」の説明が可能になる。

12. ARM とテキストマイニング

文書集合の単語共起ネットワーク、 N-gram 共起、 トピックモデル (LDA, BERTopic) は ARM と概念的に隣接する。 (1) 単語 trans = 文、 item = 単語として ARM 適用、 (2) 「医療」と「AI」が同時に出る論文集合の特徴抽出、 (3) ニュース記事の「政策 → 経済指標」連想分析、 (4) SNS の「ハッシュタグ共起」分析 (Instagram, Twitter) など、 産業界・行政・研究で幅広い。 SSDSE-B-2026 の都道府県データに自由記述レポートを組み合わせれば、 多モーダル ARM の教材になる。

13. ARM の歴史的展開とマイルストーン

(1) 1993 Agrawal, Imielinski, Swami が IBM Almaden で AIS アルゴリズム発表、 (2) 1994 Agrawal & Srikant が Apriori で剪定法を確立、 (3) 1995 Park, Chen, Yu の DHP でハッシュ最適化、 (4) 1996 Savasere, Omiecinski, Navathe の Partition で大規模対応、 (5) 2000 Han, Pei, Yin の FP-Growth で候補生成不要に、 (6) 2003 Wang, Han, Pei の Closed Pattern Mining、 (7) 2010 年代以降は GPU 並列化、 分散計算、 ストリーミング対応へと進化。 30 年以上の歴史を経ても基本概念は変わらず、 教科書的に学ぶ価値が高い。

14. ARM とプライバシー保護

市場バスケット分析は購買履歴を扱うため、 プライバシー懸念が常に存在する。 (1) Differential Privacy (Dwork 2006) で ε-DP 保証、 (2) Federated Association Rule Mining で分散データを統合せず学習、 (3) Secure Multi-party Computation でクライアント間の暗号化集計、 (4) k-anonymity, l-diversity, t-closeness などの匿名化技法。 EU GDPR, 日本の個人情報保護法、 米国 CCPA への対応は実務で必須。 SSDSE-B-2026 は公開データなのでプライバシー問題は生じないが、 企業実務では中心課題になる。

15. ARM の業界別ユースケース

(1) 小売 (Walmart, セブン-イレブン): 棚配置最適化、 クロスセル、 (2) 金融 (クレジットカード会社): 不正検知、 信用スコアリング、 (3) 医療 (病院): 症状-診断-治療パターン、 副作用検出、 (4) 通信 (NTT, au): 顧客行動分析、 解約予測、 (5) Web (Google, Facebook): クリック・コンバージョン、 (6) 製造 (Toyota, Sony): 不良品連鎖、 工程最適化、 (7) 教育 (e-learning): 学習パターン、 ドロップアウト予測。 業界ごとに「basket」「item」の定義が異なるが、 数学的枠組みは共通。

16. 締めくくり: ARM の不滅の価値

1993 年 Agrawal の Apriori 以降、 機械学習・深層学習・LLM の発展でも、 アソシエーションルールは「説明可能性の高い」「ドメイン専門家が直感的に理解できる」手法として現役。 SSDSE-B-2026 のような実データで、 ARM の数学的厳密さと業務的実用性を結びつける経験が、 データサイエンス学習者にとって貴重な教材となる。 今後 LLM がデータ分析の主流になっても、 「なぜそのルールが導かれたか」を説明する手段として ARM は残り続けるだろう。

🧮 数式に値を入れて手で計算する: アソシエーションルールの 4 指標

合成バスケットで {おむつ} → {ビール} ルールを評価する (12 件のバスケット)。

Step 1: 出現カウント

項目集合出現支持度
{おむつ}80.667
{ビール}60.500
{おむつ, ビール}50.417

Step 2: 確信度

conf = 0.417/0.667 ≈ 0.625

Step 3: リフト

lift = 0.625/0.500 = 1.250

Step 4: レバレッジ

leverage = 0.417 - 0.667×0.500 = 0.417 - 0.333 = 0.083

🐍 Python で再現

1
2
3
4
5
6
7
8
9
s_a = 8/12
s_b = 6/12
s_ab = 5/12
conf = s_ab / s_a
lift = conf / s_b
lev = s_ab - s_a*s_b
print(f"conf = {conf:.3f}")
print(f"lift = {lift:.3f}")
print(f"leverage = {lev:.3f}")

📤 実行結果

conf = 0.625 lift = 1.250 leverage = 0.083

💬 手計算 (Step 2-4) 0.625 / 1.250 / 0.083 と Python 出力が完全一致。

🎮 触って理解する

このラボのテーマは「ルールの探索」です。 個々のルールの指標を電卓のように計算する体験はアソシエーション分析のページにあります。 ここでは一歩進んで、 固定の 12 バスケットから 1 対 1 の候補ルール 20 本をすべて数え上げ最小支持度 (min_support)最小確信度 (min_confidence) の 2 本のしきい値でルール群がどう絞り込まれるかを体感します。 スライダーを動かす(または散布図のしきい値線を指/マウスでドラッグする)と、 一覧表と散布図がリアルタイムに更新されます。 上げすぎると発見がゼロになり、 下げすぎると lift ≤ 1 のノイズルールが紛れ込む ── このトレードオフがルールマイニングの核心です。

🛒 固定データ: 12 バスケット × 5 商品(● = 購入)── このデータは編集せず、 しきい値だけを動かします
📦 プリセット
🎚 しきい値
最小支持度 min_support = 0.20
最小確信度 min_confidence = 0.60
候補ルール 20 本(1 アイテム ⇒ 1 アイテム、 共起ゼロの 8 本を含む) → 採用
散布図: 各点が 1 本のルール(共起ゼロの 8 本は非表示、 同座標の点は横にずらして表示)。 lift > 1(正の関連) lift = 1(独立) lift < 1(負の関連)。 緑枠 = 採用中。 紫の縦線・青緑の横線は直接ドラッグできます。
ルール A ⇒ B |A∩B| / |A| support confidence lift 判定

💡 直感: ルールマイニング = 「数え上げ → しきい値で絞る」だけ

Apriori などのアルゴリズムが内部でやっていることは、 本質的にこのラボと同じです。 ① 候補となる組合せの出現回数を数え、 ② min_support で「そもそも滅多に起きない組合せ」を足切りし、 ③ 残った頻出集合から A ⇒ B の向きを付けて min_confidence(条件付き確率 P(B|A) の下限)で足切りする。 上の表で「|A∩B| / |A|」の列を見れば、 confidence が単なる割り算だと分かります。 デフォルト(0.20 / 0.60)では 20 本中 6 本が採用され、 その筆頭は ビール ⇒ おむつ(support 0.250、 confidence 1.000、 lift 3.00)です。 プリセット「🧱 厳しすぎ」に切り替えると、 このデータの最大支持度が 0.333(パン⇔バター)なので min_support 0.35 には 1 本も届かず発見ゼロになり、 「🌊 ゆるい」では lift < 1 の負の関連ルールまで大量に紛れ込みます。 しきい値の 2 本の線が「発見の量と質」を直接コントロールしていることを、 線をドラッグして確かめてください。

⚠️ よくある落とし穴

(1) しきい値の恣意性。 min_support / min_confidence には理論的な正解がありません。 このラボでも 0.05/0.30 なら 11 本、 0.20/0.60 なら 6 本、 0.35/0.80 なら 0 本と、 分析者の設定ひとつで「発見」の数が激変します。 実務ではしきい値を複数試す感度分析を行い、 レポートには採用した値を必ず明記します。 「有意になるまでしきい値を下げる」のは p-hacking と同型の誤りです。

(2) 組合せ爆発。 ここでは 5 商品 × 1 対 1 に限定したので候補は 20 本でしたが、 条件部・結論部に複数アイテムを許すと 5 商品でも 180 本、 50 商品では約 7 × 1023 本になり全列挙は不可能です。 min_support による足切り(枝刈り)は「趣味」ではなく、 計算を成立させるための必須の仕掛けです。 さらにルールを大量に検定すれば偶然の「有意」も大量に混じるため、 カイ二乗検定多重検定補正(本文の Bonferroni の節)が要ります。

(3) リフト無視。 デフォルト設定で採用される 6 本のうち、 バター ⇒ 牛乳は confidence 0.600 で合格に見えますが lift は 0.90、 つまり牛乳の基礎率 0.667 より低い「負の関連」です。 牛乳のような人気商品が結論部にくると confidence は自動的に高く出ます。 チェックボックス「lift > 1 のみ」を入れて、 このルールが弾かれるのを確認してください(リフト値参照)。 逆に ビール ⇒ おむつは lift 3.00 でも該当バスケットは 3 件だけ。 少数件の高 lift は偶然かもしれず、 support と lift の両にらみが欠かせません。

🚀 発展: Apriori の枝刈りと FP-Growth

全列挙が不可能な規模で探索を成立させる鍵が Apriori の反単調性(anti-monotonicity)です。 「アイテム集合を大きくすると支持度は決して増えない」ため、 例えば {ビール} 単独が min_support 未満なら、 {ビール, パン} や {ビール, パン, 牛乳} などビールを含む上位集合をすべて数えずに捨てられます。 このラボの縦線(min_support)を右に動かすと点が左側から消えていくのは、 まさにこの枝刈りを 1 対 1 ルールで見ている状態です。 FP-Growth はさらに進んで、 トランザクション全体を FP-tree という圧縮された木構造に 2 回のスキャンで格納し、 候補生成そのものを省いて頻出集合を列挙します(アイテム数が数万を超える EC ログではこちらが定番)。 こうして絞り込んだルールは「この商品を買った人はこちらも」型のレコメンドシステムの説明可能な部品になります。 なお、 採用されたルールはあくまで共起の記述であり、 棚配置やクーポンなどの介入判断には A/B テストによる因果の確認が別途必要です。

🐍 Python 実装

① SSDSE-B-2026 を読み込み、 都道府県データを 0/1 ダミー化

このコードでやること: 公的統計 SSDSE-B-2026 から 47 都道府県の 2023 年データを抽出し、 「高齢化率高 / 人口少 / 出生率低」の 3 つの真偽指標を中央値基準でダミー化する(A1101 総人口・A1303 老年人口・A4101 出生数から算出)。

📥 入力データ (SSDSE-B-2026 抜粋):

SSDSE-B-2026 Code Prefecture A1101 A1303 A4101 2023 R01000 北海道 5092000 1681000 24430 2023 R02000 青森県 1184000 417000 5696 2023 R03000 岩手県 1163000 407000 5432 ... ... ... ... ... ... 2023 R13000 東京都 14086000 3205000 86348
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932')
df = df.iloc[1:]  # 1 行目は日本語ヘッダなので除外
df['year'] = pd.to_numeric(df['SSDSE-B-2026'], errors='coerce')
pref = df[(df['year']==2023) & df['Code'].str.endswith('000')].copy()
for c in ['A1101','A1303','A4101']:
    pref[c] = pd.to_numeric(pref[c], errors='coerce')
pref['aging_rate'] = pref['A1303'] / pref['A1101']
pref['birth_rate'] = pref['A4101'] / pref['A1101']

basket = pd.DataFrame({
    'A_aging_high':  (pref['aging_rate'] > pref['aging_rate'].median()),
    'B_pop_low':     (pref['A1101']     < pref['A1101'].median()),
    'C_birth_low':   (pref['birth_rate'] < pref['birth_rate'].median()),
}).astype(int)
print(basket.head())

📤 実行結果:

A_aging_high B_pop_low C_birth_low 1 1 0 1 北海道 13 1 1 1 青森県 25 1 1 1 岩手県 37 0 0 1 宮城県 49 1 1 1 秋田県

💬 結果の読み方: 47 都道府県 × 3 アイテムの 0/1 行列が完成。 例えば青森県は (A,B,C) = (1,1,1) で「高齢化高・人口少・出生率低」の三重苦タイプ。 これでバスケットデータと完全に同型になり、 mlxtend がそのまま動かせる。

② mlxtend で Apriori → association_rules を実行

このコードでやること: ①で作った 47 県 × 3 アイテムのバスケットに対し、 mlxtend.frequent_patterns.apriori で頻出アイテム集合、 続いて association_rules でルールを生成し Lift 順に並べる。

📥 入力: ①の basket DataFrame(47 行 × 3 列の 0/1)

1
2
3
4
5
6
7
8
9
from mlxtend.frequent_patterns import apriori, association_rules

# min_support 0.3 = 47 件中 14 件以上で出現するアイテム集合のみ
freq = apriori(basket.astype(bool),
                 min_support=0.3, use_colnames=True)

rules = association_rules(freq, metric='lift', min_threshold=1.0)
rules = rules.sort_values('lift', ascending=False)
print(rules[['antecedents','consequents','support','confidence','lift']])

📤 実行結果 (主要部分):

antecedents consequents support confidence lift (A_aging_high) (B_pop_low) 0.362 0.739 1.510 (B_pop_low) (A_aging_high) 0.362 0.739 1.510

※ min_support=0.3(47 件中 15 件以上)かつ lift ≥ 1 を満たすのはこの 2 ルールのみ。 「高齢化高 ⇒ 出生率低」(support 0.298)はわずかに閾値に届かず、 min_support を 0.2 に下げると lift 1.24 で出現する(実測値)。

💬 結果の読み方: トップは 「高齢化率が高い県 ⇒ 人口が少ない県」 で Lift=1.51。 これは「ランダムに県を抽出した場合の 1.51 倍の確率で、 高齢化高県は同時に人口少県でもある」。 逆方向 (B⇒A) も Lift は同じだが Confidence は対称的に解釈する点に注意。

③ NumPy だけで Support/Confidence/Lift を手計算

このコードでやること: ライブラリに頼らず、 mlxtend が内部で何をしているかを numpy だけで再現。 結果が②と一致することを確認する。

📥 入力: ①の basket から A=A_aging_high, B=B_pop_low の 2 列だけ取り出す

1
2
3
4
5
6
7
8
9
10
11
import numpy as np

A = basket['A_aging_high'].values
B = basket['B_pop_low'].values
n = len(A)

support    = ((A==1) & (B==1)).sum() / n
confidence = ((A==1) & (B==1)).sum() / (A==1).sum()
lift       = confidence / ((B==1).sum() / n)
leverage   = support - (A==1).mean() * (B==1).mean()

print(f'Support={support:.3f}, Conf={confidence:.3f}, Lift={lift:.3f}, Lev={leverage:.3f}')

📤 実行結果:

Support=0.362, Conf=0.739, Lift=1.510, Lev=0.122

💬 結果の読み方: mlxtend の出力と完全一致。 association_rules ライブラリは内部で 「& のビット演算 → sum → 割り算」 をしているだけと分かる。 アルゴリズムの中身がブラックボックスではないことを確認することで、 結果の妥当性検証も自分でできるようになる。

④ χ² 検定で「偶然の共起」を統計的に排除

このコードでやること: Lift 1.51 が 偶然 ではなく統計的に有意な共起であることを、 scipy.stats.chi2_contingency で 2×2 分割表のカイ二乗検定により確認する。

📥 入力: ③の A, B(2×2 のクロス表に変換)

1
2
3
4
5
6
7
8
from scipy.stats import chi2_contingency

table = pd.crosstab(basket['A_aging_high'],
                    basket['B_pop_low'])
print(table)

chi2, p, dof, expected = chi2_contingency(table)
print(f'chi2={chi2:.3f}, p={p:.4f}, dof={dof}')

📤 実行結果:

B_pop_low 0 1 A_aging_high 0 18 6 1 6 17 chi2=9.372, p=0.0022, dof=1

💬 結果の読み方: p = 0.0022 で p < 0.01、 独立仮説は強く棄却される。 「高齢化高 ⇔ 人口少」の共起は偶然ではない統計的構造。 Lift=1.51 という値に、 χ² 検定の裏付けが加わって解釈の信頼性が大きく増す。 実務では 「Lift だけでなく必ず有意性検定」 を併記するのが望ましい。

⚠️ よくある落とし穴

❌ 1. min_support を下げすぎてアイテム集合が指数爆発
アイテム種類 $d$ に対し候補数は最悪 $2^d$ 個。 商品 100 種で $2^{100}$ ≈ $10^{30}$。 Apriori は 「頻出でないアイテム集合の部分集合も頻出でない」(モノトーン性)で枝刈りするが、 min_support を 0.001 などに下げると枝刈りが効かず、 メモリ枯渇&計算停止する。 まず 0.05〜0.1 で開始し、 目的に応じ段階的に下げる。
❌ 2. Confidence だけで判断すると「人気商品の罠」に落ちる
B が全顧客の 90% が買う超人気商品なら、 任意の A に対し Confidence(A⇒B) ≒ 0.9 と高くなるが、 これは A と B が独立でも起こる現象。 必ず Lift と組み合わせて評価: Lift > 1.2 などの閾値でフィルタする。
❌ 3. 多重比較で「偶然の高 Lift」が大量発生
10,000 商品のペアを総当たりで評価すれば 49,995,000 通り。 有意水準 5% で 250 万件が偶然に「有意」と判定される。 Bonferroni 補正、 FDR (Benjamini-Hochberg)、 ホールドアウト検証で再現性を確認するのが現実的な防御策。
❌ 4. 共起と因果を混同する
「ビール ⇒ おむつ」Lift=3 でも、 棚配置を変えて売上が上がるかは 別問題。 観察データから得た共起は 交絡因子(金曜夜という時間帯など)で説明可能。 介入効果を見るには A/B テストや因果推論(傾向スコア、 do-calculus)が必須。
❌ 5. 時間順序を無視している
通常のアソシエーション分析は 同一バスケット内の共起 しか見ない。 「先月本を買い、 今月続編を買う」のような時間順パタンには 系列パタン分析(GSP, PrefixSpan, SPADE) が必要。 EC のリピート購入分析や、 医療レセプトの治療経過分析でよく使われる。
❌ 6. カテゴリ階層を平坦化して粒度ミス
「ヨーグルト(全種)」と「明治ブルガリアプレーン 400g」を同列に扱うと、 細粒度のルールは Support が下がりすぎ、 粗粒度のルールは情報量が落ちる。 階層的アソシエーション分析(generalized AR)でカテゴリ階層を活用する。
❌ 7. ネガティブ・アソシエーション(負の関連)を見落とす
標準的な Apriori は Support ≥ 閾値の 頻出ペア しか拾わないため、 「A を買うと B を買わない」(Lift < 1)は通常見えない。 排他的代替品(紅茶 vs コーヒー)を発見したいなら別途 min_threshold=0.5 以下で逆検索する設計が必要。

⚠️ もう一歩深い落とし穴 8 件

基本的な落とし穴は本文上部にまとめたが、 実務で「論文化/本番運用」を意識すると追加で意識しなければならない注意点がある。 8 件にまとめる。

  1. Support の閾値を業界知識なしで決める: 0.1 や 0.01 を機械的に使うのではなく、 「最低何件あれば判断材料になるか」をビジネス側と合意してから決める。 例: 月 100 万件のレシートで Support=0.001 なら 1,000 件 → 検証可能。
  2. 双方向ルールを一つに統合し忘れる: X⇒Y と Y⇒X は別の Confidence を持つので、 両方出てくる。 重複表示の混乱を避けるには Kulczynski で集約するか、 グループ化して表示する。
  3. 季節性・トレンドの混入: 「12 月 ⇒ クリスマスケーキ」が高 Lift で出ても、 実は時期効果。 期間を切って analysis を分割する、 または「日付」を item に加えない設計が安全。
  4. 欠損トランザクション: 「item が記録されなかった」と「item を買わなかった」が区別されないと、 Negative association が誤って正方向に出る。 欠損の取り扱いを最初に決める。
  5. 多重検定問題: 数千件のルールから「Lift > 1.5」を抽出すると、 そのうち何件かは偶然。 Bonferroni 補正や FDR で全体の偽陽性率をコントロールする。
  6. ルールの安定性検証なし: 採用したルールは時間で変わる。 ブートストラップで Support と Lift の信頼区間を出し、 「3 ヶ月先でも生き残る」かを確認する。
  7. 因果と区別しない: アソシエーションは相関であって因果ではない。 介入実験(A/B テスト)で確認しないまま施策に投入しない。
  8. ルール採用後の評価指標が無い: ルールに基づいて売場を変えた・推薦を出した後、 売上やクリック率が本当に上がったかを KPI で測る仕組みを最初に作る。 これが無いとモデルが死ぬ。

🧭 5 ステップで進める実務手順

「アソシエーションルール分析を始める」と言われたとき、 何から手をつければよいかを 5 ステップで整理する。 SSDSE-B-2026 のような公的統計データでも、 オンライン小売のログでも、 基本フローは同じ。

# ステップ やること 注意点
1目的と KPI の合意「何を見つけたいか」「効果はどう測るか」を関係者で文書化数字を出すだけのプロジェクトにしない
2アイテム設計SKU そのまま / カテゴリ / ブランド / 階層的を選択。 連続値はビン化。粒度で結果が劇的に変わる
3頻出集合抽出Apriori / FP-Growth / Eclat を選び、 min_support を調整候補爆発に注意(メモリ監視)
4ルール評価とフィルタLift, Conviction, χ² で篩い分けし、 業務的に意味あるものを残す多重検定補正を忘れない
5施策と効果検証A/B テスト等で因果を確認し、 KPI へのインパクトを測定ルール≠因果。 必ず実験で確認

5 ステップのうち、 多くのチームは「3. 抽出」だけに時間を使い、 1, 2, 4, 5 が手薄になる。 結果として「面白いルールは出たが、 ビジネスに使われない」という典型的失敗が起きる。 重要度の配分は「3 が 30%、 残り 70% を 1, 2, 4, 5 に均等」くらいがちょうど良い。

🪄 まとめ ── 1 ページで思い出す

最終的な実務指針: 「意味のあるルールは少ない」「絞り込みが価値の 8 割」「採用後の効果検証で生き残る」 ── この 3 点さえ守れば、 アソシエーションルール分析は十分実用に耐える。

🗺 概念マップ

アソシエーションルールを軸に、 関連概念を上位・並列・派生で整理:

                    教師なし学習
                         │
        ┌────────────────┼────────────────┐
        │                │                │
    クラスタリング   次元削減      アソシエーション
                                          │
                ┌─────────────────────────┼─────────────────────────┐
                │                         │                         │
          頻出パタン抽出              評価指標               時系列拡張
                │                         │                         │
        ┌───────┼───────┐         ┌──────┼──────┐         ┌────────┼────────┐
     Apriori FP-Growth Eclat  Support Confidence Lift   GSP PrefixSpan SPADE
                                                          │
                                                    系列パタン分析
                                                          │
                                                   ┌──────┴──────┐
                                                 EC履歴    医療経過
  

⚙️ Apriori アルゴリズムの仕組み

基本アイデア: モノトニシティ(反単調性)

アイテム集合 $X \subseteq Y$ なら $\mathrm{Support}(X) \geq \mathrm{Support}(Y)$ が常に成り立つ。 これは 「Y を含むトランザクションは必ず X も含む」 ためで、 集合が大きくなるほど Support は単調に減少する性質を意味する。

この性質を 逆方向に活用 したのが Apriori の核心:

「ある集合 $X$ が頻出 (Support ≥ min) でなければ、 $X$ を含むすべての上位集合も頻出ではない」
→ 探索木の枝刈りができる。

擬似コード

L₁ ← {頻出 1-itemset}                          # 1 個ずつアイテムをスキャン
k ← 2
while L_{k-1} ≠ ∅:
    C_k ← 候補生成(L_{k-1})                    # k-itemset の候補
    C_k ← C_k から、 部分集合が L_{k-1} にない候補を除外(枝刈り)
    各トランザクションを 1 回スキャンして Support 計算
    L_k ← {c ∈ C_k : Support(c) ≥ min_support}
    k ← k + 1
return ∪ L_k

具体例(min_support = 2/5)

5 件のバスケット { {A,B,C}, {A,C}, {A,B}, {B,C}, {A,B,C,D} } で実行:

ステップ候補Support採否
L₁{A},{B},{C},{D}4/5, 4/5, 4/5, 1/5D 落選
C₂{AB},{AC},{BC}3/5, 3/5, 3/5全部採用
C₃{ABC}2/5採用 (=min)
L₃{ABC}2/5終了

D を含む候補 ({AD},{BD},...) は L₁ で D が落ちた時点で 一切評価しない ── これが枝刈りの効果。 もし D の出現が 1 回なら、 {AD},{BD},{CD},{ABD},{ACD},{BCD},{ABCD} の 7 候補を全て省略できる。

FP-Growth ── tree で 2 回スキャンに圧縮

Apriori の弱点は「k ごとに DB を再スキャン」「候補生成のコスト」。 FP-Growth はトランザクションを FP-tree(頻出パタン木) として 2 回目のスキャンで構築し、 そこから直接マイニングする。 大規模データで Apriori より 10〜100 倍高速。

FP-tree (例)
       root
        │
   ┌────┴─────┐
  A:4         B:1
   │          │
  ┌┴──┐       C:1
  B:3 C:1
  │
  C:2
  │
  D:1

各ノードに「アイテム名 : カウント」が乗り、 同じ接頭辞は共有される。 メモリ上で再帰的にマイニングすれば、 何度も DB を読まなくて済む。 mlxtend, Spark MLlib いずれも FP-Growth 実装を提供している。

📜 歴史的経緯

出来事
1993Agrawal, Imielinski, Swami が SIGMOD で原典論文を発表。 アソシエーションルール概念の誕生。
1994Agrawal & Srikant が Apriori アルゴリズムを VLDB で提案。 モノトニシティを使った枝刈り。
1996Srikant & Agrawal が GSP(系列パタン)を提案。
2000Han, Pei, Yin が FP-Growthを発表。 候補生成不要・高速化。
2001Pei らが PrefixSpan を発表(系列パタンの高速版)。
2003Zaki らが Eclat を改良。 垂直格納で高速化。
2014Apache Spark MLlib に FP-Growth が標準実装、 ビッグデータ対応が容易に。
2018〜深層学習推薦が主流化、 アソシエーションは 説明可能性とコールドスタート 用途に役割が再定義される。

❓ よくある質問(FAQ)

Q1. min_support の最適値は?

業界・データ規模により異なる。 EC で 1 万 SKU × 100 万トランザクションなら 0.001〜0.01、 47 都道府県のような小規模なら 0.1〜0.3。 「ルール数が手作業で読める量(10〜100 件)」を目安に二分探索的に調整する。

Q2. Lift と Confidence、 どちらを優先すべき?

用途による。 「このルールを使ったレコメンドが当たる確率」を知りたいなら Confidence。 「このペアは特別に共起しやすいか」なら Lift。 実務では両方の閾値で AND フィルタするのが定番(例: Conf ≥ 0.3 かつ Lift ≥ 1.5)。

Q3. 連続値はそのまま使えない?

通常は 離散化(ビニング)して 0/1 ダミーに変換。 本ページの SSDSE 例も「中央値で 2 値化」した。 等頻度ビン、 等幅ビン、 ドメイン知識による境界設定など複数の方法がある。 ビン境界次第で結果が変わるため、 複数設定で頑健性を確認するのが望ましい。

Q4. 結果が大量で読み切れない

対策: ① 閾値を上げる、 ② Lift 上位 N 件だけ表示、 ③ Closed Itemset(情報を失わずに圧縮した代表)に限定、 ④ ルールクラスタリング(似たアンテシデント/コンセクエントをまとめる)、 ⑤ 可視化(散布図: x=Support, y=Confidence, 色=Lift)。

Q5. Apriori と決定木はどう違う?

決定木は 「予測すべきターゲット変数」が決まっていてそれを最大限当てるためのルールを学習。 アソシエーションは 「全アイテムの組み合わせ」を網羅的に探索しターゲット不問。 探索的データ分析でアソシエーション、 教師あり予測で決定木、 と使い分ける。

🎓 発展トピック

① Maximal / Closed Itemset ── ルールの圧縮表現

通常の頻出アイテム集合は冗長({A,B} が頻出なら {A},{B} も自動的に頻出)。 これを抑えるための代表抽出:

FPClose, CLOSET+ などのアルゴリズムが closed itemset を直接マイニング。 ルール数が 1/10〜1/100 に減るため、 出力解釈が現実的になる。

② Top-K ルール抽出

min_support を決めるのが難しい場合、 「Lift 上位 K 件だけほしい」と直接指定するアプローチ。 TopKRules, TKS などのアルゴリズムが該当。 ビジネス側からは「とりあえず面白いルールを 20 件」と指示できる利点。

③ Constraint-based Mining

「コンセクエントに必ず特定商品を含む」「アンテシデントは 3 アイテムまで」など制約付き探索。 mlxtend では association_rules 後にフィルタするが、 SPMF の TopKClassRules などは 探索段階で制約を組み込み高速化 する。

④ ネガティブ・アソシエーション

「A を買うと B を買わない」(Lift < 1, 排他的)も重要。 標準 Apriori は頻出パタンしか見ないため、 ネガティブを発見するには $P(A \cap \bar{B})$ の集合に対し別途マイニングが必要。 BookCrossing データで「ハードボイルド読者はラブロマンス読まない」のような排他構造を発見できる。

⑤ Quantitative Association Rules(量的拡張)

「年齢 [30-40] かつ 年収 [400-600万] ⇒ 自動車保有」のように 連続値の範囲をアンテシデントに含めるルール。 ビニング境界を 動的に最適化する Srikant & Agrawal (1996) の手法が古典。

⑥ Multilevel Association Rules(階層化)

「乳製品 ⇒ パン」(カテゴリ階層)と「ヨーグルト ⇒ クロワッサン」(細粒度)を 同じ枠組みで扱う。 階層を上下に動かしながら適切な粒度を見つける。

⚖️ 他手法との使い分け

手法入力出力アソシエーションとの違い
アソシエーションルールバスケット (0/1)A⇒B 形式の関係教師なし、 ターゲット不問
決定木特徴量+ラベル分類規則ツリー教師あり、 ターゲット固定
クラスタリング特徴量行列グループ分け関係でなくサンプル群を作る
相関分析連続値ペア相関係数 1 つ連続値特化、 規則は出ない
協調フィルタリングユーザー×アイテム評価未評価予測値ユーザー個別予測(規則ではない)
因果推論介入+共変量因果効果 ATE介入の効果。 共起と別物

使い分けの目安

📊 ルールの可視化テクニック

① Scatter plot (Support × Confidence × Lift)

横軸 Support、 縦軸 Confidence、 点の色を Lift で染める散布図。 右上にあるほど「広く成立し信頼性も高い」、 色が濃いほど「Lift も高い」。 良いルールは右上+濃色の点。

② Matrix-based visualization

行=アンテシデント、 列=コンセクエント、 セル=Lift のヒートマップ。 ルール数が多くてもパタンを一目で把握できる。 R の arulesViz::plot(rules, method="matrix") や Python の seaborn.heatmap で実装可能。

③ Graph-based visualization

ノード=アイテム、 エッジ=ルール、 矢印の太さ=Confidence、 色=Lift。 商品間の関係構造をネットワークとして俯瞰できる。 NetworkX, Cytoscape, Gephi などで描画。

④ Parallel coordinates

複数アイテムの組み合わせをラインで結ぶ。 「3 アイテム以上のルール」を視覚化するのに有効。

📋 クイックリファレンス

目的推奨設定
スーパーのバスケット(数万行)min_support=0.01, min_confidence=0.3, min_lift=1.2
医療レセプト(100 万行超)min_support=0.001, FP-Growth, FDR 補正
公的統計の地域分析(47 件)min_support=0.3, min_lift=1.0, χ²検定併用
Web ログ(時系列重要)PrefixSpan, 系列パタン分析
レコメンド(コールドスタート)Top-K, 説明可能 Confidence 表示

🎯 やってみよう ── ワンストップ完全実装

これまでの①〜④を統合し、 SSDSE-B-2026 から「都道府県の構造的ルール」を Top-10 出力する完成版スクリプト。 環境構築 → データ取得 → ダミー化 → Apriori → 結果整形を 1 ファイルで実行できる。

⑤ 統合チュートリアル:47 都道府県の構造的ルール Top-10

このコードでやること: SSDSE-B-2026 から 4 つの指標(高齢化率、 人口、 出生率、 全国人口シェア)を抽出し、 mlxtend で Lift 上位 10 ルールを出力する完全版。

📥 入力データ: data/raw/SSDSE-B-2026.csv (565 行 × 112 列)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import pandas as pd
from mlxtend.frequent_patterns import apriori, association_rules

# 1. データ読み込み
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932').iloc[1:]
df['year'] = pd.to_numeric(df['SSDSE-B-2026'], errors='coerce')
pref = df[(df['year']==2023) & df['Code'].str.endswith('000')].copy()

# 2. 4 指標を計算
for c in ['A1101','A1303','A4101']:
    pref[c] = pd.to_numeric(pref[c], errors='coerce')
pref['aging']  = pref['A1303'] / pref['A1101']
pref['birth']  = pref['A4101'] / pref['A1101']
pref['pop_share'] = pref['A1101'] / pref['A1101'].sum()

# 3. 中央値で 0/1 ダミー化(バスケット形式)
basket = pd.DataFrame({
    'aging_high':  pref['aging']      > pref['aging'].median(),
    'pop_low':     pref['A1101']      < pref['A1101'].median(),
    'birth_low':   pref['birth']      < pref['birth'].median(),
    'share_small': pref['pop_share']  < pref['pop_share'].median(),
})

# 4. Apriori → association_rules → Top-10
freq  = apriori(basket, min_support=0.3, use_colnames=True)
rules = association_rules(freq, metric='lift', min_threshold=1.0)
top10 = rules.sort_values('lift', ascending=False).head(10)
print(top10[['antecedents','consequents','support','confidence','lift']])

📤 実行結果:

antecedents consequents support confidence lift (share_small) (pop_low) 0.489 1.000 2.043 (pop_low) (share_small) 0.489 1.000 2.043 (aging_high, share_small) (pop_low) 0.362 1.000 2.043 (aging_high, pop_low) (share_small) 0.362 1.000 2.043 (share_small) (aging_high, pop_low) 0.362 0.739 2.043 (pop_low) (aging_high, share_small) 0.362 0.739 2.043 (aging_high) (pop_low) 0.362 0.739 1.510 (pop_low) (aging_high) 0.362 0.739 1.510 (share_small) (aging_high) 0.362 0.739 1.510 (aging_high) (share_small) 0.362 0.739 1.510

💬 結果の読み方: トップ層は share_small ⇔ pop_low(Lift 2.043)── これは人口シェアが総人口の単調変換であるため share_smallpop_low同一の集合になることの数学的必然(自明ルール)。 続く 3 要素ルール(aging_high ∩ pop_low ⇒ share_small)も Confidence 1.00 で、 「高齢化高 ∩ 人口少」の県は 100% 全国シェア小。 一方「aging_high ⇔ pop_low」は Lift=1.51 と実質的な連関を示す。 birth_low を含むルールは Lift が 1.0 前後にとどまり Top-10(min_support=0.3)には残らない ── 出生率低との共起は弱い、 というのがデータの示す実態である。

📖 用語ミニ辞書

トランザクション (Transaction)
1 回の購買、 1 セッション、 1 件のレコードなど「同時に観測された」最小単位。
アイテム (Item)
バスケットに入る基本要素。 商品、 イベント、 属性値などをすべて抽象化した概念。
アイテム集合 (Itemset)
1 つ以上のアイテムの集合。 例: {パン, バター} は 2-itemset。
頻出 (Frequent)
Support が事前指定の閾値(min_support)以上であること。
アンテシデント / コンセクエント (Antecedent / Consequent)
ルール $A \Rightarrow B$ における左辺 $A$ と右辺 $B$。 「条件」と「帰結」。
モノトニシティ (Monotonicity / Anti-monotonicity)
$X \subseteq Y \Rightarrow \mathrm{Support}(X) \geq \mathrm{Support}(Y)$。 Apriori の枝刈り原理の根拠。
候補生成 (Candidate Generation)
前段の頻出 (k-1)-itemset を join して k-itemset の候補を作る手続き。
枝刈り (Pruning)
部分集合が頻出でない候補を即座に排除する操作。 Apriori の高速化の核心。

🧪 シナリオ別テンプレート

シナリオ A: 小売店の販促企画

  1. 過去 3 ヶ月の POS データを抽出(レシート ID, 商品 ID, 日時)
  2. レシート ID をキーに pivot → 0/1 行列を作成
  3. min_support=0.005(500 レシートに 1 回以上)で Apriori
  4. Lift > 2.0, Confidence > 0.3 のルールを抽出
  5. マーケティング担当と協議し、 棚配置/クロスセル提案を企画
  6. 1 ヶ月後、 介入群と対照群で売上を比較(差分の差分法)

シナリオ B: ヘルスケアの併用薬リスク調査

  1. レセプトデータから患者 ID, 処方薬 ID, 日付を抽出
  2. 「同日処方」をトランザクションとみなす(同一バスケット定義)
  3. FP-Growth で min_support=0.0001(10 万件に 1 回)
  4. 「副作用ありの転帰」をターゲットとしてフィルタ
  5. FDR ≤ 1% で多重比較補正
  6. 臨床医とドメインレビュー、 文献マイニングで因果可能性を評価

シナリオ C: Web サイトのコンバージョン改善

  1. Google Analytics からセッションログ取得
  2. 各セッションをページ閲覧の集合に変換
  3. min_support=0.01 で Apriori → 頻出パス抽出
  4. 「コンバージョンページ」が consequent のルールに限定
  5. 離脱多発ページが antecedent に頻出するルールから改善余地特定
  6. A/B テストで改善後ページの効果を確認

シナリオ D: 公的統計の地域分析(本ページの例)

  1. SSDSE-B-2026 から最新年度・都道府県データを抽出(47 行)
  2. 連続量指標(人口・高齢化率・出生率・全国人口シェア 等)を中央値で 2 値化
  3. min_support=0.3(14 件以上で出現)で Apriori
  4. Lift, Confidence, Conviction を併用評価
  5. χ² 検定で偶然の共起ではないことを確認
  6. 結果を都道府県類型化のインプットとして利用

🎯 指標値の解釈早見表

Support

バスケット規模別の意味
0.5+超頻出(コンビニの飲み物等、 ほぼ全員)
0.1〜0.5高頻度(人気商品の組合せ)
0.01〜0.1中頻度(実務的に意味あるルール)
0.001〜0.01稀(医療レセプト等の異常検知)
<0.001超稀(偶然と区別困難)

Confidence

意味
1.00完全な含意(A を買うと必ず B も買う)
0.7〜1.0強い含意(実用的ルール候補)
0.3〜0.7中程度(要 Lift 併用評価)
<0.3弱い(基本的に不採用、 ただし Lift が極端に高ければ参照可)

Lift

解釈
> 10非常に強い共起(特殊な組み合わせ。 偶然か確認)
3〜10強い共起(実務で有用、 報告レベル)
1.5〜3中程度(多くの実務ルールはここ)
1.0〜1.5弱い正の関連(Support と組み合わせて評価)
≈ 1.0独立(情報なし)
< 1.0負の関連(排他、 競合商品など)

🛠 トラブルシュート

エラー 1: MemoryError / 計算が終わらない

原因: min_support が小さすぎて頻出アイテム集合が爆発。 対策: ① min_support を 10 倍に上げる、 ② Apriori → FP-Growth に切り替え、 ③ 稀少アイテムを事前に除去(Support < 0.001 のアイテム削除)、 ④ Spark MLlib で分散実行。

エラー 2: 出力ルールが 0 件

原因: 閾値が厳しすぎ、 またはアイテム同士の共起が薄い。 対策: ① min_support / min_threshold をログスケールで段階的に下げる、 ② num_itemsets=len(basket) を明示、 ③ basket がスパース過ぎないか確認(密度 10% 以下なら閾値見直し)。

エラー 3: TypeError on boolean basket

原因: mlxtend は内部で True/False を期待。 int 0/1 を渡すと警告 or エラー。 対策: basket.astype(bool) で型を揃える、 または fpgrowth(basket.astype(bool), ...)

エラー 4: 同じルールが両方向で重複出力

原因: A⇒B と B⇒A が別ルールとして出力される(Confidence が方向ごとに異なるため)。 対策: 分析目的に応じ、 ① frozenset で antecedent ∪ consequent をキーにユニーク化、 ② antecedent サイズが小さい方だけ保持する、 など後処理で重複除去。

エラー 5: 解釈不能なルールが大量出力

原因: 「人気アイテム同士が機械的に高 Support」現象。 対策: ① ドメイン知識で trivial なルールを除外({食パン}⇒{バター}など自明な組合せ)、 ② Lift とともに Conviction や Kulczynski を併用、 ③ Closed itemset に限定。

🤖 機械学習推薦との比較

「Amazon のレコメンド」は多くがアソシエーションではなく 協調フィルタリング + 行列分解 + 深層学習。 では今なぜアソシエーションを学ぶのか?

観点アソシエーションML 推薦 (CF / DL)
説明可能性○ 「Aを買った人の73%がBも買う」△ ブラックボックス
コールドスタート○ アイテムベースで対応× ユーザー履歴必須
パーソナライズ精度△ 全ユーザー共通◎ 個人最適化
計算コスト○ 軽量(前計算)△ GPU/大規模学習
スパースデータ耐性○ 強い△ 行列分解で吸収
監査・規制対応◎ ルール提示で説明容易× SHAP 等の解釈技術必要

結論: 現代の推薦システムは 「ML 推薦をメインに、 アソシエーションで補助/フォールバック/説明可能ルール表示」 という ハイブリッドが定石。 また、 規制業界(医療、 金融)では 説明可能性 が要件のため、 アソシエーションが第一選択となることも多い。

🔄 R 言語との対応

R では arules / arulesViz パッケージが定番。 Python (mlxtend) との対応:

操作Python (mlxtend)R (arules)
頻出アイテム集合apriori(basket, min_support=0.05)apriori(trans, parameter=list(supp=0.05))
ルール生成association_rules(freq, metric='lift')apriori(..., parameter=list(supp=, conf=))
FP-Growthfpgrowth(basket, ...)fim4r パッケージ
可視化seaborn / networkxarulesViz::plot(rules)
系列パタンspmf-pyarulesSequences::cspade

R 版の方が可視化機能 (arulesViz) が充実しているため、 ルール探索・分析フェーズで R を使い、 本番システム連携で Python (Spark MLlib FP-Growth) を使う、 というハイブリッドも一般的。

📑 詳細ケース: 都道府県 4 指標の全ルール集

SSDSE-B-2026 から 4 指標 (高齢化率高, 人口少, 出生率低, シェア小) を 2 値化し、 min_support=0.3 で Apriori を回した結果の 主要ルール一覧

アンテシデントコンセクエントSupportConfLift解釈
高齢化高 ∩ 人口少シェア小0.3621.0002.043三重指標で地方確定
シェア小 ∩ 高齢化高人口少0.3621.0002.043同値(順列違い)
シェア小 ∩ 人口少高齢化高0.3620.7391.510シェア小∩人口少=人口少(同一集合)なので R1 と一致
高齢化高シェア小0.3620.7391.510share_small≡pop_low ゆえ高齢化⇒人口少と同値
シェア小高齢化高0.3620.7391.510対称性(R1 と一致)
高齢化高 ∩ 出生率低人口少0.2130.7141.460少子高齢→人口減
人口少 ∩ 出生率低高齢化高0.2130.9091.858人口減・少子→高齢
高齢化高出生率低0.2980.6091.244高齢の県の6割は少子
高齢化高人口少0.3620.7391.510代表ルール
人口少出生率低0.2340.4780.977ほぼ独立(Lift<1、共起は偶然並み)

解釈ポイント

📝 より正確な分析(教材補足): 上表・解釈は SSDSE-B-2026(2023 年 47 都道府県)で再計算した実測値に基づく。 share_small(人口シェア中央値未満)は pop_low(総人口中央値未満)と数学的に同一集合のため、 両者を含むルールは自明(Lift 2.043)で新情報を持たない。 「人口少 ⇒ 出生率低」は Lift≈0.98<1(2×2 表 11 県 ≒ 独立期待 11.3 県、 χ²≈0・p≈1.0)で無相関。 したがって「高齢化・人口減・少子化の三重苦が一体で進む」という図式は 2023 年データでは部分的で、 実測上は 高齢化↔人口規模 の連関が中心となる。

注意事項

この分析は 47 サンプルで実施しており、 統計的検出力は限定的。 ルールは 相関構造の記述として読むべきで、 因果関係(例: 高齢化が出生率を下げる)は別途、 自然実験や時系列パネルデータで検証する必要があります。

📊 図で掴む ── アソシエーションルールの分布と構造

アソシエーションルール分析の結果を表だけで眺めると、 個々のルールの数字に圧倒されて全体像を見失う。 ここでは SSDSE-B-2026 都道府県 47 件を「高齢化率 高/低」「人口 多/少」「出生率 高/低」「全国人口シェア 大/小」のダミー変数(item)にエンコードしたあと、 算出された Support / Confidence / Lift の分布そのものを 3 つの可視化で見渡す。 こうすると「ほとんどのルールは Lift=1 付近に集中する/一部のルールだけが極端」という構造が一目で分かる。

① 散布図: Support × Confidence (ルール 1 件 = 1 点)

x 軸に Support、 y 軸に Confidence を取り、 点の色を Lift で塗ると、 右上(高 Support × 高 Confidence)にあるほど「頻出で当たり前のルール」、 左上(低 Support × 高 Confidence)にあるほど「珍しいが起きると確実なルール」だと読める。 SSDSE-B では右上に「人口少 ⇒ 全国人口シェア小」の自明ルールが密集し、 左上に「高齢化率高 ⇒ 出生率低」のような地方構造を映すルールが点在する。

ルールの Support × Confidence 散布図

図 r520-1: 抽出されたルールの Support × Confidence 散布図(分布イメージ)。 右上ほど「みんなが知っていて外れない」当たり前のルール。 左上ほど「珍しいが起きると確実」のレアルール。

この散布図を見ずに表だけ眺めると、 Lift=1.5 の中ほどのルールを過大評価しがち。 散布図は「全体に対して、 そのルールが分布のどこに位置しているか」を強制的に意識させる装置として効く。

② ヒストグラム: Lift の分布 (独立=1 からのズレ)

Lift は「もし前件と後件が独立なら 1」になる指標。 全ルールの Lift 値をヒストグラムにすると、 ほとんどが Lift=1 付近に集中し、 ロングテールで Lift=2 や Lift=3 のルールが少数だけ顔を出す。 これは「大半のルールは独立で意味がない」「本当に意味があるルールは少数の外れ値」という構造を示す。

Lift 値の分布ヒストグラム

図 r520-2: 全ルールの Lift 値ヒストグラム(分布イメージ)。 Lift=1 付近に大きな山があり、 Lift>2 の領域はごく少数しかない。

ヒストグラムの「Lift=1 の山」が大きいほど、 そのアイテム集合は実は互いに独立に近い。 つまり association_rules() が大量に出力したルールの 90% 以上は「偶然の共起」に過ぎない可能性が高い。 だからこそ minimum lift threshold(例: lift > 1.2)でのフィルタが実務では必須となる。

③ 箱ひげ図: Lift の前件サイズ別分布

前件(antecedent)に含まれる item 数を 1, 2, 3 と変えたとき、 Lift 値の分布がどう動くかを箱ひげで比較する。 一般に前件サイズが増えるほどルールは具体的になり Lift は上がりやすい(ただし Support は下がる)。 SSDSE-B では前件サイズ 2 のときに Lift の中央値が 1.5 付近まで上がるが、 サイズ 3 では Support 不足で外れ値が支配的になる。

前件サイズ別の Lift 分布 箱ひげ図

図 r520-3: 前件サイズ別 Lift 値分布。 サイズが大きくなるほど Lift は上振れするが、 ばらつきも増える。

この図から学べる実務指針: 「前件サイズは小さく保つ(1〜2 個)」のが解釈性とサンプル数のバランスで最も実用的。 サイズ 3 以上は「面白いが追試できない」傾向にある。

3 つの図を Python 1 セルで再現する

このコードでやること: SSDSE-B-2026 を読み込み、 4 指標を 2 値化し、 mlxtend で Apriori → association_rules を実行、 散布図・ヒストグラム・箱ひげの 3 図を一度に保存する。

📥 入力データdata/raw/SSDSE-B-2026.csv 抜粋):

SSDSE-B-2026 Code Prefecture A1101 A1303 A4101 2023 R01000 北海道 5092000 1681000 28000 2023 R02000 青森県 1184000 417000 6000 2023 R13000 東京都 14086000 3155000 95000 ... ... ... ... ... ...
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from mlxtend.frequent_patterns import apriori, association_rules

# 1. SSDSE-B-2026 を cp932 で読み込み、2 行目の日本語ヘッダを除外
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932').iloc[1:]
df['year'] = pd.to_numeric(df['SSDSE-B-2026'], errors='coerce')
pref = df[(df['year']==2023) & df['Code'].str.endswith('000')].copy()

# 2. 実在列 A1101/A1303/A4101 から連続量指標を計算
for c in ['A1101','A1303','A4101']:
    pref[c] = pd.to_numeric(pref[c], errors='coerce')
pref['aging'] = pref['A1303'] / pref['A1101']
pref['birth'] = pref['A4101'] / pref['A1101']
pref['pop_share'] = pref['A1101'] / pref['A1101'].sum()

# 3. 中央値で 0/1 ダミー化(バスケット形式)
basket = pd.DataFrame({
    'aging_high':  pref['aging']     >= pref['aging'].median(),
    'pop_low':     pref['A1101']     <  pref['A1101'].median(),
    'birth_low':   pref['birth']     <  pref['birth'].median(),
    'share_small': pref['pop_share'] <  pref['pop_share'].median(),
})

# 4. Apriori → ルール生成 → 3 図を描画
freq = apriori(basket, min_support=0.10, use_colnames=True)
rules = association_rules(freq, metric='lift', min_threshold=0.5)
rules['ant_size'] = rules['antecedents'].apply(len)

fig, axes = plt.subplots(1, 3, figsize=(15, 4.5))
axes[0].scatter(rules['support'], rules['confidence'],
                c=rules['lift'], cmap='viridis', alpha=0.7)
axes[0].set_xlabel('Support'); axes[0].set_ylabel('Confidence')
axes[1].hist(rules['lift'], bins=30, edgecolor='black')
axes[1].set_xlabel('Lift'); axes[1].set_ylabel('Frequency')
axes[2].boxplot([rules[rules['ant_size']==k]['lift']
                 for k in [1,2,3]], tick_labels=['1','2','3'])
axes[2].set_xlabel('Antecedent size'); axes[2].set_ylabel('Lift')
plt.tight_layout(); plt.savefig('rules_3figs.png', dpi=120)
print('saved:', len(rules), 'rules')

📤 実行例:

saved: (ルール数) rules 散布図 右上(自明・高支持): aging_high ∧ pop_low ⇒ share_small (sup=0.36, conf=1.00, lift=2.05) 散布図 代表ルール: aging_high ⇒ pop_low (sup=0.36, conf=0.74, lift=1.51) ヒスト: Lift=1.0 付近に最大ピーク(大半のルールは独立近傍で情報が薄い) 箱ひげ: 前件サイズが大きいほど Lift 中央値は上振れするが、 ばらつきも増える

💬 結果の読み方: ルールの大半は Lift≒1(独立、 つまり無意味)に集中し、 意味のある共起はロングテールの少数に限られる。 そこから Lift>1.5 を採用し、 さらに前件サイズを 1〜2 に絞れば「実務で使える」少数のルールが残る。 → アソシエーションルールは「大量に作って、 統計的に絞る」のが正しい使い方。 具体値は 4 指標の中央値 2 値化の結果に依存する(本ページ Python ①〜④ が再現可能な検証済みルール)。

📝 理解度チェック ── 10 問で自己診断

アソシエーションルールの落とし穴は「指標の意味を取り違える」「Support と Confidence と Lift の三角関係を曖昧にする」の 2 点に集約される。 以下 10 問は、 実務で「やってしまいがちな誤解」を狙い撃ちにしている。 1 問 30 秒で解いて、 最後の解説で答え合わせをして欲しい。

# 問題 選択肢
Q1 Support の定義として正しいものは? (a) X⇒Y の確率 / (b) X∩Y の出現割合 / (c) X が来たとき Y が来る条件付き確率 / (d) X と Y の独立性
Q2 Confidence が 1.0 のルールが必ず「強い因果」を示すと言えるか? (a) はい / (b) いいえ、 Support が低いと意味がない / (c) 必ず Y → X も成り立つ
Q3 Lift = 1 のルールが意味するのは? (a) 前件と後件が独立 / (b) 100% の確率 / (c) 偶然のレベルを超える共起
Q4 min_support を下げると何が起きる? (a) ルール数増加・計算時間増加 / (b) ルール数減少 / (c) Confidence が下がる
Q5 Apriori の「反単調性」とは? (a) 子集合が頻出でなければ親集合も頻出ではない / (b) 親集合が頻出なら子集合も頻出 / (c) すべての集合は単調増加する
Q6 連続変数(高齢化率 32.1% など)をそのまま Apriori に投入するとどうなる? (a) 各値がユニーク item となり Support が極端に小さくなる / (b) 自動的に区間化される / (c) エラーになる
Q7 Lift と相関係数の関係は? (a) どちらも独立性を 1 や 0 で示す / (b) Lift は相関係数の絶対値そのもの / (c) Lift は方向(正/負)を区別しない
Q8 FP-Growth が Apriori より速い理由は? (a) tree 構造でデータベース全体を圧縮しスキャン 2 回で済む / (b) GPU を使う / (c) 並列化されている
Q9 「おむつ ⇒ ビール」伝説が現代でそのまま当てはまらない理由は? (a) 都市伝説で実証がない / (b) Lift が低かった / (c) min_support が高すぎた
Q10 Conviction の定義は? (a) (1-Support(Y)) / (1-Confidence) / (b) Support(X∩Y) - Support(X)Support(Y) / (c) Lift と同じ
▼ 解答と解説を見る
# 正解 解説
Q1(b)Support は P(X∩Y) ── 全トランザクション中で X と Y が同時に現れる割合。 確率と紛らわしいが「割合」と覚える方が直感的。
Q2(b)Confidence=1.0 でも Support が極小(例: 0.001)なら、 たった数件の偶然で 100% になっただけ。 サンプル数を必ず併記する。
Q3(a)Lift = P(Y|X)/P(Y) なので、 X と Y が独立なら P(Y|X)=P(Y) となり Lift=1。 1 から離れるほど共起の偏りが強い。
Q4(a)min_support を下げると候補集合が爆発し、 ルール数と計算時間が急増する。 メモリ枯渇の原因 No.1。
Q5(a)反単調性(Apriori property): 子集合が頻出でない(min_support 未満)なら、 その親集合は絶対に頻出にならない。 これで枝刈りが効く。
Q6(a)連続変数はそのままだと各値がユニーク item 扱いになり、 Support がほぼ 1/N。 ビン化(区間化)してから投入するか、 中央値で 2 値化する。
Q7(c)Lift は X と Y が「同時に起きやすい度合い」を独立基準=1 で測る。 一方、 相関係数 r は -1 から +1 まで方向を区別する。 Lift >1 は正相関と類似だが値の対応関係はない。
Q8(a)FP-Tree(Frequent Pattern Tree)を 1 回目スキャンで構築し、 2 回目で頻出パタンを再帰的に抽出。 Apriori の k 回スキャンより圧倒的に速い。
Q9(a)Walmart の事例として有名だが、 原典は曖昧で再現報告がない都市伝説。 ただし「直観に反するルール発見」の比喩としては有用。
Q10(a)Conviction = (1-Support(Y)) / (1-Confidence)。 Confidence=1 のとき無限大、 独立のとき 1。 Lift と違って「ルールが破れた頻度」を測る非対称指標。

採点目安: 9-10 問正解 = 実務投入レベル、 7-8 問 = 監督下なら OK、 5-6 問 = もう一度本文を読み直そう、 4 問以下 = Support/Confidence/Lift の定義から復習。

📊 指標 11 種類の完全比較表

アソシエーションルール分析では Support / Confidence / Lift の 3 大指標だけでなく、 状況に応じて 10 種類以上の補助指標が使われる。 以下は実務でよく登場する 11 種類を一覧化したもの。 列「独立時の値」「最大値」「対称性」を併記したので、 自分の分析に合うものを選ぶときの目安にして欲しい。

指標名 定義式(簡略) 独立時 最大 対称性 主な用途
SupportP(X∩Y)P(X)P(Y)min(P(X),P(Y))対称頻度フィルタ
ConfidenceP(Y|X) = P(X∩Y)/P(X)P(Y)1非対称予測精度
LiftP(Y|X)/P(Y)11/max(P(X),P(Y))対称独立性検出
Conviction(1-P(Y))/(1-Conf)1非対称含意の強さ
LeverageP(X∩Y) - P(X)P(Y)00.25対称独立からの差分
JaccardP(X∩Y)/P(X∪Y)類似度依存1対称集合類似度
CosineP(X∩Y)/√(P(X)P(Y))√(P(X)P(Y))1対称ベクトル類似度
All-ConfidenceP(X∩Y)/max(P(X),P(Y))類似度依存1対称不均衡対策
Kulczynski(Conf(X⇒Y)+Conf(Y⇒X))/2類似度依存1対称不均衡対称化
χ² 統計量Σ(O-E)²/E0N対称統計的検定
相互情報量Σ p(x,y)log p(x,y)/(p(x)p(y))0H(X) or H(Y)対称情報理論

選び方の目安:
① 頻出フィルタ目的なら Support 一択 / ② 「X が起きたとき Y が起きやすいか」を非対称に見たいなら Confidence / ③ 偶然との差を見たいなら Lift か Leverage / ④ クラス不均衡が激しいなら All-Confidence や Kulczynski / ⑤ 統計的に「無相関」を棄却したいなら χ² 検定。
実務では「Support + Lift + χ²」の 3 点フィルタを順に適用するのが定石。

📖 ミニ辞典 ── アソシエーション分析周辺の 20 語

論文や実装ドキュメントを読むときに「これは何だっけ?」と止まらないように、 周辺で頻出する 20 語を一気に整理する。 各語は基準ページの関連語ともリンクしているので、 詳細はリンク先で深掘りして欲しい。

用語 説明
トランザクション一回の購買・閲覧・観測など、 アイテム集合の単位レコード。 レシート 1 枚、 来訪セッション 1 回が典型例。
アイテム / アイテム集合トランザクションに含まれる要素単位(商品 ID、 カテゴリなど)と、 その有限部分集合。
頻出アイテム集合min_support 以上の支持率をもつアイテム集合。 Apriori が探索する対象。
前件 (antecedent)ルール X⇒Y の X 側。 「条件」や「仮定」と訳されることもある。
後件 (consequent)ルール X⇒Y の Y 側。 「結論」や「推論」と呼ばれることも。
Maximal frequent itemset部分集合を含まない最大の頻出集合。 出力ルールを圧縮するときに使う。
Closed frequent itemsetSupport が同値となる親集合を持たない頻出集合。 Maximal と Frequent の中間表現。
Top-K miningmin_support を明示せず「上位 K 件のルールだけ欲しい」とする変種。 ヒープ管理で効率化する。
Quantitative rule「年齢 [30-40)」のように連続値を区間化したルール。 区間境界の決め方が品質を左右する。
Multilevel rule「飲料」→「炭酸飲料」→「コカ・コーラ」のような階層構造を含むルール。
Negative association「X を買うと Y を買わない」型のルール。 補完財/競合財の検出に有効。
Sequential pattern時間順序付きのアイテム列に対するパターンマイニング。 PrefixSpan などが代表。
FP-Treeトランザクション集合を圧縮するプレフィックスツリー。 FP-Growth の中核データ構造。
EclatEquivalence Class Transformation。 ビット集合の交差で Support を求める縦型方式。
Conviction(1-P(Y))/(1-Confidence)。 Confidence と Lift の中間的役割で「ルールがどれだけ強く含意するか」を示す。
All-ConfidenceP(X∩Y)/max(P(X), P(Y))。 X, Y の不均衡に頑健な対称指標。
Kulczynski 指数(Conf(X⇒Y) + Conf(Y⇒X))/2。 不均衡データで Lift が暴れるときの代替。
Imbalance Ratio (IR)|P(X)-P(Y)| / (P(X)+P(Y)-P(X∩Y))。 1 に近いほど不均衡。
バスケット分析アソシエーション分析の小売分野での呼び名。 ABC 分析と組み合わせるのが王道。
Curse of dimensionalityitem 数が増えると候補集合が指数的に増加し、 計算量と意味のなさが両方爆発する。

🔬 深掘り追記 ── リフトの死角・冗長ルールの整理・小標本の推測

本ページの用語対照表に一行だけ登場した Kulczynski / Imbalance Ratio / 閉じた頻出集合 を、 実際の数字で動かして補強する追記。 既出の落とし穴(多重比較・人気商品の罠・稀少アイテム)とは別の、 「リフトそのものが持つ構造的な弱点」と「n=47 でルールをどこまで信じてよいか」に焦点を当てる。

⚠️ リフトの死角: 零トランザクション問題(null-invariance)

例 1 の架空のレシート 1,000 枚(パン 600・バター 500・同時 400)に、 パンもバターも含まないレシートを 9,000 枚継ぎ足して n=10,000 にしてみる。 パンとバターの関係自体は 1 ミリも変わっていないのに、 指標は次のように動く(架空データによる思考実験)。

n = 1,000: Lift = 0.400/(0.600×0.500) = 1.33 n = 10,000: Lift = 0.040/(0.060×0.050) = 13.33 ← 10 倍に膨張 Kulczynski = ½(400/600 + 400/500) = 0.733 (両者で不変) IR = |600−500|/(600+500−400) = 0.143 (両者で不変)

Lift の分母 $P(A)P(B)$ は「A も B も含まない行」が増えるだけで小さくなるため、 無関係なトランザクションを足すほど Lift は勝手に上がる。 この性質を「null-invariant でない」と呼ぶ。 一方 $\mathrm{Kulc}(A,B) = \tfrac{1}{2}\{P(B \mid A) + P(A \mid B)\}$ と $\mathrm{IR} = |P(A)-P(B)| \,/\, \{P(A)+P(B)-P(A \cap B)\}$ は A・B の行だけから決まるので不変(null-invariant)。 全店舗ログのように「対象カテゴリと無関係なカゴ」が大量に混ざるデータでは、 Lift のランキングは分析対象の切り出し方ひとつで一変する。 Kulc で強さ・IR で偏りを併読し、 Lift は「同じトランザクション集合内での比較」に限って使うのが安全。

🧊 冗長ルールの整理: 閉じた頻出集合と極大頻出集合

手法選択フローで名前だけ出た Closed Itemset の中身。 頻出集合 $X$ が「$X$ と同じ Support を持つ真の上位集合が存在しない」とき閉じた(closed)、 「頻出な真の上位集合が存在しない」とき極大(maximal)と呼ぶ。 極大 ⊆ 閉 ⊆ 頻出 の包含関係にあり、 閉集合だけ保存すれば全頻出集合の Support を無損失で復元できる(極大は個数が最少だが Support 情報を落とす)。

本ページの代表ルール表がまさに好例で、 share_smallpop_low は同一集合のため R5 は R1 の完全な複製だった。 {pop_low} は {pop_low, share_small} と Support が同じ ── つまり {pop_low} は閉じていない ── ので、 閉集合マイニング(mlxtend では fpmax が極大版)を使えばこの種の複製ルールは列挙の段階で自動的に潰せる。 アイテム数が増えるほどルール本数は閉集合ベースで桁単位に減り、 多重比較の母数(検定回数)も同時に減るという一石二鳥の前処理になる。

📏 n=47 でルールを信じてよいか ── 区間推定と正確検定

R1「pop_low ⇒ aging_high」の 2×2 表(17, 6 / 6, 18)は 47 県しかない。 Confidence 0.739 はあくまで点推定で、 二項比率 17/23 の Wilson 95% 信頼区間は [0.535, 0.875] と幅が広い(信頼区間)。 それでも関連の有無自体は、 Fisher の正確検定で p ≈ 0.0012(オッズ比 8.5)、 Yates 補正付き χ² ≈ 9.37(p ≈ 0.0022、 カイ二乗検定)と明瞭に有意。 本ページの 4 ダミーから作れる 1⇒1 の有向ルールは 4×3 = 12 本なので、 Bonferroni 補正後も 0.0012 × 12 ≈ 0.015 < 0.05 で生き残る(多重比較)。

教訓は二つ。 (1) 小標本では「Lift 1.51」の一点だけでなく、 正確検定の p 値と Confidence の区間をセットで報告する(区間はブートストラップでも可)。 (2) 補正の母数は「作り得たルール総数」で数える ── 有意に見えたルールだけ数えて補正すると偽陽性対策にならない。 R1 のように補正後も残るルールだけが、 解釈(相関であって因果ではない)に進む資格を持つ。

📝 より正確な分析(教材補足): 本節の Fisher 正確検定・χ²・Wilson 区間は、 本ページ例 2 の 2×2 表(SSDSE-B-2026 [cp932, 2 行目ラベル行除外]・2023 年 47 都道府県・実在列 A1101/A1303 由来)から scipy / statsmodels で再計算した検証済みの値。 零トランザクションの数値例はパン・バターの架空データによる思考実験であり、 実データの主張ではない。 指標の定義と使い分けの全体像はアソシエーション分析、 条件付き確率としての Confidence の読み方は条件付き確率ベイズの定理、 ルールの応用先は推薦システムリフト値を参照。

🔗 隣接手法への橋渡し

アソシエーションルール X⇒Y は、 トランザクション化 → 頻出集合列挙 → ルール生成 → 評価のパイプラインで動く。

SSDSE-B-2026 で「{高齢化率_高, 人口密度_低} → {一次産業_高}」が lift=2.1 で得られた場合、 これは共起構造の記述であって因果ではない点を明示し、 政策議論に使うときの解釈の責任を分離する。

🌳 手法選択フロー

アソシエーションルール抽出の選択は「アイテム数」「希少パターンの重要度」「順序の有無」の 3 軸で判定。

  1. アイテム数の規模: 数十~千 → Apriori で十分。 数万以上 → FP-Growth (1 パスで FP-tree 構築) が高速。 SSDSE-B-2026 を二値化したアイテム数は 100 前後で Apriori 一択。
  2. 稀なパターンも見たい? Yes → support 閾値を下げる + lift 閾値を上げる。 No → support>=0.3 で計算量削減。 「沖縄だけに現れる稀パターン」を見つけたい場合は閉じた頻出集合 (Closed Itemset) 抽出。
  3. 時間順序を含むか? No → 通常のアソシエーションルール。 Yes (例: 5 年間の購買履歴) → Sequential Pattern Mining (PrefixSpan, GSP)。 目的変数付き → Subgroup Discovery。

確信度 confidence + リフト lift の 2 指標だけでなく、 conviction (1-support(Y))/(1-confidence) や leverage (P(X∩Y)-P(X)P(Y)) も併用すると redundant rule 除去が容易。