作者:小dull鸟
来源:Python数据分析之禅
Python绘制箱形图全解
数据挖掘工作中的第一步就是异常值检测,异常值的存在会影响实验结果。箱形图主要是为了检测异常值,箱形图最大的优点就是不受异常值的影响,能够准确稳定地描绘出数据的离散分布情况,同时也利于数据的清洗。
举个例子:
有一组学生成绩数据:
[59, 60, 67, 70, 73, 76, 78, 85, 87, 90, 92, 540]
我们想看一下有没有手误输错的成绩,那么就可以用箱形图来判断
计算成绩数据的5种值:
1.下四分位数Q1
Qi所在位置=i(n+1)/4,其中i=1,2,3。n表示序列中包含的项数。
Q1所在的位置=(12+1)/4=3.25
Q1=0.75×第三项+0.25×第四项=0.75×67+0.25×70=67.75
2.中位数(第二个四分位数)Q2
Q1所在的位置=2(12+1)/4=6.5
Q1=0.5×第六项+0.5×第七项=0.5×76+0.5×78=115
3.上四分位数Q3
Q3所在的位置=3(12+1)/4=9.75
Q3=0.25×第九项+0.75×第十项=0.25×87+0.75×90=89.25
4.上限
上限是非异常范围内的最大值。
首先要知道什么是四分位距如何计算的?
四分位距IQR=Q3-Q1,那么上限=Q3+1.5IQR
5.下限
下限是非异常范围内的最小值
下限=Q1-1.5IQR
该学生成绩数据的箱形图可以这样画:
发现有1个异常值,明显是手误打错的
上面这些过程可以直接用pyecharts实现,非常方便
一、基本箱形图
from pyecharts import options as opts
from pyecharts.charts import Boxplot
v1 = [
[850, 740, 900, 1070, 930, 850, 950, 980, 980, 880, 1000, 980],
[960, 940, 960, 940, 880, 800, 850, 880, 900, 840, 830, 790],
]
v2 = [
[890, 810, 810, 820, 800, 770, 760, 740, 750, 760, 910, 920],
[890, 840, 780, 810, 760, 810, 790, 810, 820, 850, 870, 870],
]
b=(
Boxplot()
.add_xaxis(["2019年", "2020年"])
.add_yaxis("A", Boxplot().prepare_data(v1))
.add_yaxis("B", Boxplot().prepare_data(v2))
.set_global_opts(title_opts=opts.TitleOpts(title="基本箱形图"))
)
b.render_notebook()
prepare_data可以对数据进行处理,得到上述的5种值
二、显示异常值的箱形图
经过研究发现,Boxplot的prepare_data模块不会判断并自动画出异常值,于是我对它进行了改进(源码在文末)
from pyecharts import options as opts
from pyecharts.charts import Boxplot,Scatter,Grid
y_data = [
[850,740,900,1070,930,850,950,980,80,880,1000,980,930,650,760,810,1000,1000,960,960,],
[960,940,960,940,880,800,850,880,900,840,830,790,810,880,880,830,800,790,760,800,],
[880,880,880,860,720,720,620,860,970,950,880,910,850,870,840,840,850,840,840,840,],
[890,810,810,820,800,770,760,740,750,760,910,920,890,860,880,720,840,850,850,780,],
[890,840,780,810,760,810,790,810,820,850,870,870,810,740,810,940,950,800,810,870,],
]
box_plot = Boxplot()
data1, scatter_datas=box_plot.prepare_data(y_data) #对prepare_data模块进行改进,返回两个列表
box_plot = (
box_plot.add_xaxis(xaxis_data=["一班","二班","三班","四班","五班"])
.add_yaxis(series_name="", y_axis=data1)
.set_global_opts(
tooltip_opts=opts.TooltipOpts(trigger="item", axis_pointer_type="shadow"),
xaxis_opts=opts.AxisOpts(
type_="category",
boundary_gap=True,
splitarea_opts=opts.SplitAreaOpts(is_show=False),
splitline_opts=opts.SplitLineOpts(is_show=False),
),
yaxis_opts=opts.AxisOpts(
type_="value",
name="总分数",
splitarea_opts=opts.SplitAreaOpts(
is_show=True, areastyle_opts=opts.AreaStyleOpts(opacity=1)
),
),
)
.set_series_opts(tooltip_opts=opts.TooltipOpts(formatter="{b}: {c}"))
)
scatter = (
Scatter()
.add_xaxis(xaxis_data=["","","","",""])
.add_yaxis(series_name="", y_axis=scatter_datas)
.set_global_opts(
title_opts=opts.TitleOpts(
pos_left="10%",
pos_top="90%",
title="成绩数据异常值",
title_textstyle_opts=opts.TextStyleOpts(
border_color="#999", border_width=1, font_size=14
),
),
yaxis_opts=opts.AxisOpts(
axislabel_opts=opts.LabelOpts(is_show=False),
axistick_opts=opts.AxisTickOpts(is_show=False),
),
)
)
grid = (
Grid()
.add(
box_plot,
grid_opts=opts.GridOpts(pos_left="10%", pos_right="10%", pos_bottom="15%"),
)
.add(
scatter,
grid_opts=opts.GridOpts(pos_left="10%", pos_right="10%", pos_bottom="15%"),
)
)
grid.render_notebook()
对prepare_data模块进行改进,返回两个列表,第一个是和之前的5个值一样,第二个是异常值组成的列表。
-完-
完整代码请扫码关注公众号并回复“20200921”获取