数据分析实战|a/b测试探寻哪种广告点击率更高?(代码片段)

Dream丶Killer Dream丶Killer     2022-11-29     530

关键词:

大家好,我是丁小杰。

本篇是《数据分析实战》系列第三篇,案例来源为《数据分析实战》一书,书中使用的是 R 语言,接下来一段时间,我会用 Python + Tableau/Pyecharts 尽可能的将案例复现出来,以供大家学习。

场景描述

某个促销活动每个月都会开展一次,但和公司其他类似的促销活动相比,该促销活动的用户购买率比较低。通过调查用户购买率低的原因,发现问题可能出在促销广告上。

于是我们准备了两个不同的广告,来验证哪种广告能够带来更高的用户购买率。

A/B测试

A/B 测试能够在多个选项中找出那个能够带来最佳结果的选项。在本例中,我们只要同时投放广告 A 和广告 B,就可以排除其他外部因素的干扰,但要注意用户分组必须遵循随机原则。

在测试过程中,我们收集到了两组广告的曝光数据和点击数据,接下来就可以开始数据分析!

数据描述

ab_test_imp

广告曝光次数信息,87924 行。

字段类型含义
log_datestr广告曝光日期
app_namestr应用名
test_namestr测试名
test_casestr测试用例(A/B)
user_idnumpy.int64用户 ID
transaction_idnumpy.int64事务 ID
ab_test_goal

广告点击次数信息,8598 行。

字段类型含义
log_date.gstr广告点击日期
app_namestr应用名
test_name.gstr测试名
test_case.gstr测试用例(A/B)
user_id.gnumpy.int64用户 ID
transaction_idnumpy.int64事务 ID

数据分析

数据读取

读取两个数据集。

import pandas as pd

imp_df = pd.read_csv('ab_test_imp.csv')
goal_df = pd.read_csv('ab_test_goal.csv')

修改两个数据集的列名。

imp_df.columns = ['广告曝光日期', '应用名', '测试名', '测试用例(A/B)', '用户ID', '事务ID']
goal_df.columns = ['广告点击日期', '应用名', '测试名', '测试用例(A/B)', '用户ID', '事务ID']

显示 ab_test_imp 数据集后五行。

imp_df.tail()

显示 ab_test_goal 数据集后五行。

goal_df.tail()

以曝光数据作为主数据集,连接两个数据集。

all_df = imp_df.merge(goal_df, how='left', on='事务ID', suffixes=('', '_goal'))
all_df.tail()

增加标记列,判断用户是否点击

all_df['是否点击'] = all_df['用户ID_goal'].apply(lambda x:0 if pd.isnull(x) else 1)

提取分析所需的列数据。

all_df = all_df.loc[:, ['广告曝光日期', '测试用例(A/B)', '用户ID',  '事务ID', '是否点击']]
all_df.tail()

A/B点击率

数据处理好后,接下来统计一下 A/B 两个广告的点击率。

pivot = all_df.pivot_table(index='测试用例(A/B)',
                           columns=None,
                           values='是否点击',
                           aggfunc=(lambda x: sum(x)/len(x))).reset_index()
pivot

A 的点击率为 是 8% 左右,而 B 的点击率 11.5%。

卡方检验

在讨论二者的差异时,一般采用卡方检验,我们先获取 A/B 广告的点击次数。

import numpy as np

pivot = all_df.pivot_table(index='测试用例(A/B)',
                           columns='是否点击',
                           values='用户ID',
                           aggfunc=np.count_nonzero)
pivot

chi2_contingency 用于列联表中变量独立性的卡方检验。
chi2_contingency(observed, correction=True, lambda_=None)

参数

  • observed:列联表,本例中为二维数组。
  • correction :如果为True,并且自由度为1,则应用Yates校正以保持连续性。校正的效果是将每个观察值向相应的期望值调整0.5
  • lambda_ :float或str,可选。默认情况下,此测试中计算的统计量是Pearson的卡方统计量。 lambda_允许使用Cressie-Read功率散度族的统计量来代替。

返回值

  • chi2:float,卡方值

  • p:float,p值

  • dof:int,自由程度

  • expected:ndarray,预期频率,基于表的边际总和

from scipy.stats import chi2_contingency

kf = chi2_contingency(np.array(pivot))
kf

根据上面结果,p值为 $ 4.04×10^-69 $ ,
是一个非常小的数值。p 值越接近于 0 差异性越大。通常来说,当 p 值 小于 0.05 时,称为“存在显著性差异”。因此我们可以说:在将两种广告分为 A/B 并 同时投放后,所得到的点击率存在显著性差异。

A/B广告点击时间序列

计算两个广告每日的点击率。

res = all_df.pivot_table(index='广告曝光日期',
                  columns='测试用例(A/B)',
                  values='是否点击',
                  aggfunc=(lambda x: sum(x)/len(x))).reset_index()
res.head()

绘制A/B广告点击率时间序列折线图。

from pyecharts.charts import *
import pyecharts.options as opts
from pyecharts.globals import ThemeType

line_style = 
    'normal': 
        'width': 4,
        'shadowColor': 'rgba(155, 18, 184, .3)', 
        'shadowBlur': 10,
        'shadowOffsetY': 10,
        'shadowOffsetX': 10,
        'curve': 0.5  
    


line = (Line(init_opts=opts.InitOpts(theme='ThemeType.CHALK', width='900px')))

line.add_xaxis(res['广告曝光日期'].tolist())
line.add_yaxis('A 广告',
        res['A'].tolist(),
        yaxis_index=0,
        is_smooth=True,
        is_symbol_show=False,
        linestyle_opts=line_style
    )
line.add_yaxis('B 广告',
        res['B'].tolist(),
        is_smooth=True,
        is_symbol_show=False,
        linestyle_opts=line_style
    )
line.set_series_opts(
        label_opts=opts.LabelOpts(
            is_show = False,
        )
    )
line.set_global_opts(
        title_opts=opts.TitleOpts(
            title = 'A / B 广告点击率时间序列变化折线图',
            pos_left = 'center',
            pos_top = '2%'
        ),
        legend_opts=opts.LegendOpts(
            pos_top = '12%',
            legend_icon = 'circle'
        ),
        xaxis_opts=opts.AxisOpts(
            axislabel_opts='rotate':90,
            axisline_opts=opts.AxisLineOpts(
                is_show=False
            ),
        ),
        yaxis_opts=opts.AxisOpts(
            name='点击率 %',
            axisline_opts=opts.AxisLineOpts(
                is_show=False
            ),
            splitline_opts=opts.SplitLineOpts(
                is_show=True
            )
        ),
        tooltip_opts=opts.TooltipOpts(
            is_show = True,
            trigger = 'axis',
            trigger_on = 'mousemove|click',
            axis_pointer_type = 'shadow'
        )
    )

line.render_notebook()


通过上图可知,广告 B 的点击率在大多数时候都优于广告A。所以,分析结果是,广告B比广告A更容易被用户点击。

这就是今天要分享的内容,记得点赞哦!

案例参考

[1]《数据分析实战》 [日] 酒卷隆志 里洋平/著 肖峰/译


对于刚入门 Python 或是想要入门 Python 的小伙伴,可以通过下方小卡片联系作者,一起交流学习,都是从新手走过来的,有时候一个简单的问题卡很久,但可能别人的一点拨就会恍然大悟,由衷的希望大家能够共同进步。另有整理的近千套简历模板,几百册电子书等你来领取哦!

👇🏻 关注公众号卡片,回复“交流群”,一起学习Python👇🏻

使用a/b测试的目的是什么?

...到我们的目标,我们常常都需要对重要页面或功能进行A/B测试,但是还是有很多运营新人对A/B测试有些懵逼,今天就和大家一起来扒一扒A/B测试的理由,希望可以帮助大家更好的开展网络运营工作。 先看前10条 1. 结合了大数... 查看详情

《机器学习实战》之k-近邻算法

看了这本书的第一个算法—k-近邻算法,这个算法总体构造思想是比较简单的,在ACM当中的话就对应了kd树这种结构。首先需要给定训练集,然后给出测试数据,求出训练集中与测试数据最相近的k个数据,根据这k个数据的属... 查看详情

电商小程序实战教程-广告维护功能(代码片段)

我们在广告管理章节,搭建了列表页面和整体框架,我们这一节实现一下广告的新增和广告的修改功能。广告新增切换到广告新增页面,添加一个表单容器组件。表单场景选择新增,数据源选择广告组件会根据数据源的字段自动... 查看详情

电商小程序实战教程-广告管理(代码片段)

一般我们的小程序都会有个轮播图,我们把轮播图单独建一个数据源用来存放日常商家的宣传图片,这样便于维护。新建数据源在控制台中点击新建数据源,输入名称和标识新建一个轮播图的字段模型应用中添加页面新增了数据... 查看详情

数据分析实战|pandas交叉列表探寻用户数下降的原因(代码片段)

大家好,我是丁小杰。本篇是《数据分析实战》系列第二篇,案例来源为《数据分析实战》一书,书中使用的是R语言,接下来一段时间,我会用Python+Tableau尽可能的将案例复现出来,以供大家学习。场... 查看详情

火山引擎datatester:a/b测试,让企业摆脱广告投放“乱烧钱”

“我知道在广告上的投资有一半是无用的,但问题是我不知道是哪一半。”——零售大亨约翰·沃纳梅克这句经典名言,被称为广告界的哥特巴赫猜想,它道出了广告效果衡量的难点,同样也击中了无数广告主的... 查看详情

一文快速了解火山引擎a/b测试平台

...果推断的「黄金标准」,是效果评估的利器。火山引擎A/B测试(DataTester)是一站式大规模的在线A/BTesting和智能调优平台,它基于稳定可靠的分流能力、科学完善的统计引擎、智能的调优算法,提供了从制定优化目标,到实验设... 查看详情

第53课:spark大型项目广告点击项目技术骨架实现之spark+kafka+flume实战

FlumeFlume是Cloudera提供的一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的系统,Flume支持在日志系统中定制各类数据发送方,用于收集数据;同时,Flume提供对数据进行简单处理,并写到... 查看详情

奶牛跟蜗牛,哪种动物智商更高?——t检验帮你找到答案

奶牛跟蜗牛,都是“牛”,那么哪种动物更“牛”,智商更高呢?此时就能用到T检验来找答案~ T检验(独立样本T检验),用于分析定类数据与定量数据之间的关系情况。例如,在本研究中,我们想探究奶牛跟蜗牛的智商平均值... 查看详情

a/b测试

...版本与当前版本用户体验的变化,收集数据并分析,根据数据分析结果衡量更改对业务的影响,可以确保每个更改都产生正向结果,从而消除创新 查看详情

一年40万次实验,字节跳动a/b测试平台是怎么炼出来的?

2012年,刚刚建立的字节跳动便开启了A/B测试之旅,随着今日头条、抖音、西瓜视频等全线业务的使用,将A/B测试应用在产品命名、交互设计、推荐算法、用户增长、广告优化和市场活动等各方面决策上。据今年4月字... 查看详情

数据分析实战|探寻销售额下降的原因(代码片段)

大家好,我是丁小杰。本文案例的来源为《数据分析实战》一书,书中使用的是R语言,接下来一段时间,我会用Python+Tableau尽可能的将案例复现出来,以供大家学习。场景描述某公司经营的一款APP小游戏... 查看详情

数据分析实战|pandas交叉列表探寻用户数下降的原因(代码片段)

大家好,我是丁小杰。本篇是《数据分析实战》系列第二篇,案例来源为《数据分析实战》一书,书中使用的是R语言,接下来一段时间,我会用Python+Tableau尽可能的将案例复现出来,以供大家学习。场... 查看详情

1132:零起点学算法39——多组测试数据(a+b)

1132:零起点学算法39——多组测试数据(a+b)TimeLimit:1Sec  MemoryLimit:64MB  64bitIOFormat:%lldSubmitted:1790  Accepted:1222[Submit][Status][WebBoard]Description计算a+b.很多的题目测试数据会有很多组的,一般我们 查看详情

搭建高性价比的油液压力测试环境,经验诚可贵,看看哪种方案最适合你?

【系列专栏】:博主结合工作实践输出的,解决实际问题的专栏,朋友们看过来!《QT开发实战》《嵌入式通用开发实战》 查看详情

1134:零起点学算法41——多组测试数据(a+b)iii

1134:零起点学算法41——多组测试数据(a+b)IIITimeLimit:1Sec  MemoryLimit:64MB  64bitIOFormat:%lldSubmitted:1585  Accepted:1174[Submit][Status][WebBoard]Description对于多组测试数据,还有一些是没有明确告诉你多少 查看详情

r语言实战-数据类型-2(数据框dataframe)(代码片段)

5、数据框dataframe data.frame创建data.frame() 1>a<-c(1,2,3,4,5)2>b<-c(‘a‘,‘b‘,‘c‘,‘d‘,‘e‘)3>c<-c(T,F,F,F,T)4>x<-data.frame(a,b,c)5>x6abc711aTRUE822bFALSE933cFALSE1044dFA 查看详情

复习测试

(选择一项)A:B:C:D:正确答案是 B 您回答的是 C回答错误试题分析纠错设为收藏(选择二项)5A:B:C:D:正确答案是 A,C 您回答的是 A,B回答错误试题分析纠错设为收藏(选择一项)6A:B:C:D:正确答案是 B 您没有回答... 查看详情