# 商务案例: 购物篮数据关联分析¶

# 1. 关联分析Python库 - mlxtend¶

mlxtend (http://rasbt.github.io/mlxtend/) 是一款高级的机器学习扩展库，可用于日常机器学习任务的主要工具，也可以作为sklearn的一个补充和辅助工具。

In [4]:

    import pandas as pd
    # pip install mlxtend
    from mlxtend.preprocessing import TransactionEncoder
    from mlxtend.frequent_patterns import apriori

# 2. 针对购物篮数据开展关联分析¶

## 2.1. 构造示例数据集如下：¶

In [5]:

    dataset = [['牛奶', '洋葱', '肉豆蔻', '芸豆', '鸡蛋', '酸奶'],
            ['莳萝', '洋葱', '肉豆蔻', '芸豆', '鸡蛋', '酸奶'],
            ['牛奶', '苹果', '芸豆', '鸡蛋'],
            ['牛奶', '独角兽', '玉米', '芸豆', '酸奶'],
            ['玉米', '洋葱', '洋葱', '芸豆', '冰淇淋', '鸡蛋']]

In [6]:

    dataset

Out[6]:

    [['牛奶', '洋葱', '肉豆蔻', '芸豆', '鸡蛋', '酸奶'],
     ['莳萝', '洋葱', '肉豆蔻', '芸豆', '鸡蛋', '酸奶'],
     ['牛奶', '苹果', '芸豆', '鸡蛋'],
     ['牛奶', '独角兽', '玉米', '芸豆', '酸奶'],
     ['玉米', '洋葱', '洋葱', '芸豆', '冰淇淋', '鸡蛋']]

## 2.2. 将上述数据集转换为购物篮数据¶

In [7]:

    te = TransactionEncoder()

In [8]:

    te_ary = te.fit(dataset).transform(dataset)
    te_ary

Out[8]:

    array([[False,  True,  True, False, False,  True,  True, False, False,
             True,  True],
           [False,  True, False, False, False,  True,  True, False,  True,
             True,  True],
           [False, False,  True, False, False, False,  True,  True, False,
            False,  True],
           [False, False,  True,  True,  True, False,  True, False, False,
             True, False],
           [ True,  True, False, False,  True, False,  True, False, False,
            False,  True]])

In [9]:

    df = pd.DataFrame(te_ary, columns = te.columns_)
    df

Out[9]:

| 冰淇淋 | 洋葱 | 牛奶 | 独角兽 | 玉米 | 肉豆蔻 | 芸豆 | 苹果 | 莳萝 | 酸奶 | 鸡蛋
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
0 | False | True | True | False | False | True | True | False | False | True | True
1 | False | True | False | False | False | True | True | False | True | True | True
2 | False | False | True | False | False | False | True | True | False | False | True
3 | False | False | True | True | True | False | True | False | False | True | False
4 | True | True | False | False | True | False | True | False | False | False | True

## 2.3. 使用Apriori算法找出频繁项集¶

In [10]:

    from mlxtend.frequent_patterns import apriori
    freq = apriori(df, min_support = 0.5, use_colnames = True)

In [11]:

    freq

Out[11]:

| support | itemsets
--- | --- | ---
0 | 0.6 | (洋葱)
1 | 0.6 | (牛奶)
2 | 1.0 | (芸豆)
3 | 0.6 | (酸奶)
4 | 0.8 | (鸡蛋)
5 | 0.6 | (洋葱, 芸豆)
6 | 0.6 | (洋葱, 鸡蛋)
7 | 0.6 | (牛奶, 芸豆)
8 | 0.6 | (芸豆, 酸奶)
9 | 0.8 | (鸡蛋, 芸豆)
10 | 0.6 | (洋葱, 鸡蛋, 芸豆)

In [12]:

    freq = apriori(df, min_support = 0.5, use_colnames = False)
    freq

Out[12]:

| support | itemsets
--- | --- | ---
0 | 0.6 | (1)
1 | 0.6 | (2)
2 | 1.0 | (6)
3 | 0.6 | (9)
4 | 0.8 | (10)
5 | 0.6 | (1, 6)
6 | 0.6 | (1, 10)
7 | 0.6 | (2, 6)
8 | 0.6 | (9, 6)
9 | 0.8 | (10, 6)
10 | 0.6 | (1, 10, 6)

In [16]:

    freq = apriori(df, min_support = 0.5, use_colnames = True)

## 2.4. 生成关联规则¶

In [13]:

    from mlxtend.frequent_patterns import association_rules
    Rules = association_rules(freq, metric = "confidence", min_threshold = 0.8)
    Rules

Out[13]:

| antecedents | consequents | antecedent support | consequent support | support | confidence | lift | leverage | conviction
--- | --- | --- | --- | --- | --- | --- | --- | --- | ---
0 | (1) | (6) | 0.6 | 1.0 | 0.6 | 1.0 | 1.00 | 0.00 | inf
1 | (1) | (10) | 0.6 | 0.8 | 0.6 | 1.0 | 1.25 | 0.12 | inf
2 | (2) | (6) | 0.6 | 1.0 | 0.6 | 1.0 | 1.00 | 0.00 | inf
3 | (9) | (6) | 0.6 | 1.0 | 0.6 | 1.0 | 1.00 | 0.00 | inf
4 | (10) | (6) | 0.8 | 1.0 | 0.8 | 1.0 | 1.00 | 0.00 | inf
5 | (6) | (10) | 1.0 | 0.8 | 0.8 | 0.8 | 1.00 | 0.00 | 1.0
6 | (1, 10) | (6) | 0.6 | 1.0 | 0.6 | 1.0 | 1.00 | 0.00 | inf
7 | (1, 6) | (10) | 0.6 | 0.8 | 0.6 | 1.0 | 1.25 | 0.12 | inf
8 | (1) | (10, 6) | 0.6 | 0.8 | 0.6 | 1.0 | 1.25 | 0.12 | inf

In [14]:

    type(Rules)

Out[14]:

    pandas.core.frame.DataFrame

In [15]:

    Rules2 = Rules[['antecedents', 'consequents', 'support', 'confidence']]
    Rules2

Out[15]:

| antecedents | consequents | support | confidence
--- | --- | --- | --- | ---
0 | (1) | (6) | 0.6 | 1.0
1 | (1) | (10) | 0.6 | 1.0
2 | (2) | (6) | 0.6 | 1.0
3 | (9) | (6) | 0.6 | 1.0
4 | (10) | (6) | 0.8 | 1.0
5 | (6) | (10) | 0.8 | 0.8
6 | (1, 10) | (6) | 0.6 | 1.0
7 | (1, 6) | (10) | 0.6 | 1.0
8 | (1) | (10, 6) | 0.6 | 1.0

In [16]:

    Rules3 = Rules2[Rules2['confidence'] >= 0.9]
    Rules3

Out[16]:

| antecedents | consequents | support | confidence
--- | --- | --- | --- | ---
0 | (1) | (6) | 0.6 | 1.0
1 | (1) | (10) | 0.6 | 1.0
2 | (2) | (6) | 0.6 | 1.0
3 | (9) | (6) | 0.6 | 1.0
4 | (10) | (6) | 0.8 | 1.0
6 | (1, 10) | (6) | 0.6 | 1.0
7 | (1, 6) | (10) | 0.6 | 1.0
8 | (1) | (10, 6) | 0.6 | 1.0

# 3. 从外部导入数据进行分析¶

In [17]:

    import numpy as np
    import matplotlib.pyplot as plt

In [18]:

    # 读取外部数据
    purchase_data = pd.read_csv('./PurchaseData.csv', header = None, keep_default_na = False)

In [19]:

    purchase_data.head()

Out[19]:

| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
0 | shrimp | almonds | avocado | vegetables mix | green grapes | whole weat flour | yams | cottage cheese | energy drink | tomato juice | low fat yogurt | green tea | honey | salad | mineral water | salmon | antioxydant juice | frozen smoothie | spinach | olive oil
1 | burgers | meatballs | eggs |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
2 | chutney |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
3 | turkey | avocado |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
4 | mineral water | milk | energy bar | whole wheat rice | green tea |  |  |  |  |  |  |  |  |  |  |  |  |  |  |

In [20]:

    num_records = len(purchase_data)
    num_records

Out[20]:

    7501

## 3.1. 数据预处理¶

In [21]:

    records = []
    for i in range(0, num_records):
        records.append([str(purchase_data.values[i, j]) for j in range(0, 20)])

In [22]:

    records[2]
    # 去除空值
    for i in range(0, num_records):
         records[i] = [x for x in records[i] if x]

In [23]:

    records[1]

Out[23]:

    ['burgers', 'meatballs', 'eggs']

In [24]:

    te_ary = te.fit(records).transform(records)
    te_ary[0]

Out[24]:

    array([False,  True,  True, False,  True, False, False, False, False,
           False, False, False, False, False, False, False, False, False,
           False, False, False, False, False, False, False, False, False,
           False, False, False, False, False, False,  True, False, False,
           False, False, False,  True, False, False, False, False, False,
           False, False, False,  True, False, False, False, False,  True,
            True, False, False, False, False, False,  True, False, False,
           False, False,  True, False, False, False, False, False, False,
            True, False, False, False, False, False, False, False, False,
            True, False, False, False, False, False, False, False, False,
           False,  True,  True, False, False, False, False,  True, False,
           False, False, False,  True, False, False, False,  True, False,
           False, False, False,  True, False, False,  True, False, False,
            True, False, False])

In [25]:

    df = pd.DataFrame(te_ary, columns = te.columns_)
    df.head()

Out[25]:

| asparagus | almonds | antioxydant juice | asparagus | avocado | babies food | bacon | barbecue sauce | black tea | blueberries | ... | turkey | vegetables mix | water spray | white wine | whole weat flour | whole wheat pasta | whole wheat rice | yams | yogurt cake | zucchini
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
0 | False | True | True | False | True | False | False | False | False | False | ... | False | True | False | False | True | False | False | True | False | False
1 | False | False | False | False | False | False | False | False | False | False | ... | False | False | False | False | False | False | False | False | False | False
2 | False | False | False | False | False | False | False | False | False | False | ... | False | False | False | False | False | False | False | False | False | False
3 | False | False | False | False | True | False | False | False | False | False | ... | True | False | False | False | False | False | False | False | False | False
4 | False | False | False | False | False | False | False | False | False | False | ... | False | False | False | False | False | False | True | False | False | False

5 rows × 120 columns

## 3.2. 关联规则挖掘¶

In [26]:

    # 生成频繁项集
    freq = apriori(df, min_support = 0.05, use_colnames = True)

In [27]:

    freq

Out[27]:

| support | itemsets
--- | --- | ---
0 | 0.087188 | (burgers)
1 | 0.081056 | (cake)
2 | 0.059992 | (chicken)
3 | 0.163845 | (chocolate)
4 | 0.080389 | (cookies)
5 | 0.051060 | (cooking oil)
6 | 0.179709 | (eggs)
7 | 0.079323 | (escalope)
8 | 0.170911 | (french fries)
9 | 0.063325 | (frozen smoothie)
10 | 0.095321 | (frozen vegetables)
11 | 0.052393 | (grated cheese)
12 | 0.132116 | (green tea)
13 | 0.098254 | (ground beef)
14 | 0.076523 | (low fat yogurt)
15 | 0.129583 | (milk)
16 | 0.238368 | (mineral water)
17 | 0.065858 | (olive oil)
18 | 0.095054 | (pancakes)
19 | 0.071457 | (shrimp)
20 | 0.050527 | (soup)
21 | 0.174110 | (spaghetti)
22 | 0.068391 | (tomatoes)
23 | 0.062525 | (turkey)
24 | 0.058526 | (whole wheat rice)
25 | 0.052660 | (mineral water, chocolate)
26 | 0.050927 | (eggs, mineral water)
27 | 0.059725 | (spaghetti, mineral water)

In [28]:

    # 计算关联规则
    Rules = association_rules(freq, metric = "confidence", min_threshold = 0.2)
    Rules

Out[28]:

| antecedents | consequents | antecedent support | consequent support | support | confidence | lift | leverage | conviction
--- | --- | --- | --- | --- | --- | --- | --- | --- | ---
0 | (mineral water) | (chocolate) | 0.238368 | 0.163845 | 0.052660 | 0.220917 | 1.348332 | 0.013604 | 1.073256
1 | (chocolate) | (mineral water) | 0.163845 | 0.238368 | 0.052660 | 0.321400 | 1.348332 | 0.013604 | 1.122357
2 | (eggs) | (mineral water) | 0.179709 | 0.238368 | 0.050927 | 0.283383 | 1.188845 | 0.008090 | 1.062815
3 | (mineral water) | (eggs) | 0.238368 | 0.179709 | 0.050927 | 0.213647 | 1.188845 | 0.008090 | 1.043158
4 | (spaghetti) | (mineral water) | 0.174110 | 0.238368 | 0.059725 | 0.343032 | 1.439085 | 0.018223 | 1.159314
5 | (mineral water) | (spaghetti) | 0.238368 | 0.174110 | 0.059725 | 0.250559 | 1.439085 | 0.018223 | 1.102008

In [ ]: