还记得啤酒和尿不湿的故事吗?我用Python带你一起玩玩关联规则!

论坛 期权论坛 期权     
数据分析1480   2019-7-20 09:56   2002   0
大部分朋友应该听过“啤酒”和“尿布”的故事——超市分析顾客的商品购买记录,发现“啤酒”和“尿布”经常被一起购买,背后的原因是美国家庭婴儿一般由母亲在家照顾,年轻的父亲到超市购买尿布时会顺便买上自己喜欢的啤酒(暂且不论故事的真实性)。


关联分析可以看做是对多个类别变量做相关性分析,也就是现象(事物)A和现象(事物)B同时出现的频繁程度。比如定义两个事件——A:出现乌云,B:下雨——不考虑事件的先后顺序,从我们的日常生活经验很容易发现,出现乌云的时候,大多数时候都会下雨,也就是说这两个事件是高度关联的。

针对零售购物的关联分析也被称之为购物篮分析(Market Basket Analysis),如上面的“啤酒”和“尿布”的案例。购物篮分析在于发现经常被一起购买的商品组合,对应的业务场景可以是:
  • 优化商品布局,e.g. 超市可以把关联度高的商品摆放在一起,便于顾客一起挑选;
  • 设计促销方案,e.g. 两种关联度高的商品一起搭配购买可以享受价格优惠;

  • 快速商品推荐,通常在电商业务中使用。e.g. 顾客浏览某一商品,页面上会推荐“经常一起购买的产品”或者“90%的顾客也看了如下商品”等规则进行推荐。



注:当当网的图书推荐



关联分析中的关键指标
例如,现在有如下交易数据。



定义X,Y是两个不相交的项目(事物或者现象),那么:


  • 支持度(support)表示X,Y同时出现的概率,公式表示如下


    上述表格中西红柿和鸡蛋同时出现的订单数为3,总订单数为5,那么西红柿->鸡蛋的支持度为3/5.
  • 置信度(confidence)表示发生X的集合中,出现Y的概率,即


    上述表格中西红柿和鸡蛋同时出现的订单数为3,出现西红柿的订单数为4,那么西红柿->鸡蛋的置信度为3/4.

  • 提升度(lift),衡量X,Y之间的相关性,如果lift>1表示两者之间存在关联性(会一起出现);lift=1表示两者之间没有关系(两个事件相互独立);lift鸡蛋的提升度为
    .


现在,我们想用关联分析方法来分析近10年来(2010年至今)的国产电影中哪些演员会经常搭档,或者说经常同台演出的演员组合。



第一步,准备数据
我们去豆瓣上抓点数据,目标网址是https://movie.douban.com/tag/#/,可以筛选对应的标签,网页请求返回的数据都是json格式,很容易抓取。

爬虫主体代码如下(headers部分需要配置),单个查询条件下的最大抓取数据量为1W条。
page_idx = 1
mark_run = 1
while mark_run == 1:
    # 进度提示
    sys.stdout.write('\r当前进度 第%d页'%page_idx)
    sys.stdout.flush()
    time.sleep(0.1)

    # 页面标记
    mark_page = str((page_idx-1)*20)

    url = 'https://movie.douban.com/j/new_search_subjects?sort=S&range=0,10&tags=%E7%94%B5%E5%BD%B1&start='+mark_page+'&countries=%E4%B8%AD%E5%9B%BD%E5%A4%A7%E9%99%86&year_range=2010,2019'
    r = requests.get(url, headers=headers)

    if r.status_code == 200:
        # 获取html中的返回数据并重编码
        html_text = r.content.decode('utf-8')

        # 转化为json格式
        html_json = json.loads(html_text)

        # 如果超出数据范围,则返回的数据为空,此时停止爬取
        if len(html_json['data'])>0:
            # 数据转为dataframe
            df_tmp = pd.DataFrame(html_json['data'])
        else:
            mark_run = 0
            continue

        # 整个每个页面的数据
        if page_idx == 1:
            df_data = df_tmp
        else:
            df_data = pd.concat([df_data,df_tmp],axis=0)
    else:
        print('网页报错'+url)
        continue

    page_idx += 1

# 数据保存
df_data.to_csv('爬虫数据_豆瓣电影2010-2019_20190715.csv',index=False)



第二步,数据清洗。
注:这里只是进行粗略的清洗,豆瓣对电影的标签可能存在错误。
# 载入数据
data_movie = pd.read_csv('爬虫数据_豆瓣电影2010-2019_20190715.csv')

# 国外导演的作品要剔除掉,按导演的名称来提取
# 外国人的名称中含有·,此方法无法辨认外籍华人导演,比如温子仁
data_movie = data_movie[~data_movie['directors'].str.contains('·')]

# 筛选有导演且有演员的电影,空值为'[]',通常是节目类
data_movie = data_movie[(data_movie['directors'] !='[]') & (data_movie['casts'] != '[]') ]

# 筛选分析会用到的列
data_movie = data_movie[['id','title','directors','casts','rate','star','url']]

# 解析演员列表
cast_info = list()
for i in data_movie['casts']:
    # 去除多余的字符(非分隔字符)
    tmp = re.sub("\[|\]|\'",'',i)
    # 统一分隔字符,存在中文空格、中文逗号、顿号、英文/分割
    tmp_cast = re.sub("\s|\/|\\|\|| |,|、|;",',',tmp).split(',')
    # 去除空值
    tmp_cast = [i for i in tmp_cast if i!='']
    cast_info.append(tmp_cast)
解析得到的演员信息
  1. cast_info
复制代码
是一个列表,查看前5个值,可以看到如下格式的数据:


第三步,关联分析。
先转化成分析要用的数据格式,即一行表示一部电影,列表示演员是否出现(0表示没有出现,1代表出现)。
# 对list格式的数据转化为展开的01矩阵(或者用true,false表示)
from mlxtend.preprocessing import TransactionEncoder
te = TransactionEncoder()
te_ary = te.fit(cast_info).transform(cast_info)
df_casts = pd.DataFrame(te_ary, columns=te.columns_)
得到的dataframe如下:



可以看到,列名就是展开的演员名单,其中还有外国演员,需要筛选中文名称的演员,操作如下。
# 筛选中文名称演员

# 演员名称,列名
col_names = df_casts.columns

# 保存筛选后的列名
casts_selected = list()

for col_name in col_names:

    # 名字至少有两个中文字符
    i_cn = re.findall('[\u4e00-\u9fa5]{2,}',col_name)

    # 不含英文字母
    i_en = re.findall('[A-Za-z]',col_name)

    if len(i_cn)>0 and len(i_en)==0 and len(col_name)1)]
casts_group_top = casts_group.sort_values(by=['support'],ascending=False).head(10)
casts_group_top['合作电影数量'] = casts_group_top['support']*data_movie.shape[0]
casts_group_top

结果如下:



想不到啊想不到,居首位的居然是潘长江老师,看看潘老师近10年的作品:
data_movie[data_movie['casts'].str.contains('潘长江')]

可以发现有个“连续剧电影”《毛驴县令》出了16部,每部都有潘长江和宛琼丹两位演员,这也是上榜的主要原因。
注:《毛驴县令》系列 https://movie.douban.com/subject_search?search_text=%E6%AF%9B%E9%A9%B4%E5%8E%BF%E4%BB%A4&cat=1002&start=0
董卿和朱军组合的出境倒是有点神奇,说好的电影呢?看了数据才知道,豆瓣是把《春节联欢晚会》也打上了“电影”的标签,而主演就是各位主持人(这波操作……),不过我们也顺带发现了这两位主持人可谓是春晚的“黄金搭档”。



查看关联分析的详细指标数据。
rules.sort_values(by = ['support','confidence'],ascending=False).head(10)

得到的数据如下:


注:上表中的leverage和conviction也是衡量关联度的指标。


【星球伙伴招募】
限时招募100个粉丝登录星球,一起学习和成长!

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:10
帖子:2
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP