赞
踩
箱线图,是一种专门用于显示一组数据分散情况的统计图,通常呈现出一个箱子的形状。这种图形的主要作用是反映原始数据的分布特征,以及进行多组数据分布特征的比较。
每一个箱子都包含一些关键的数学统计量,比如中位数、上四分位数(Q3)、下四分位数(Q1)、最大值、最小值等,它们共同揭示了数据的中心位置和散布范围。这些信息不仅能分析不同类别数据各层次水平的差异,还能揭示数据间的离散程度、异常值、以及分布差异等信息。
在python中可以使用`matplotlib`和`seaborn`第三方库,来绘制箱线图
两种方法的区别
使用 Matplotlib 库中的 pyplot 模块绘制箱线图。它提供了基本的箱线图功能,但可能不如其他专门针对数据可视化的库(如 Seaborn)那么美观和易用。
使用 Seaborn 库绘制箱线图。Seaborn 是一个基于 Matplotlib 的数据可视化库,它提供了更高级的绘图功能,如更美观的样式、颜色映射等。使用 Seaborn 绘制箱线图可以使图形更加美观和易于理解。
总结:如果你需要一个简单的箱线图,可以使用Matplotlib ;如果你希望获得更好的视觉效果和更丰富的功能,可以使用 Seaborn。
下面来介绍一下使用Seaborn如何绘制箱线图
代码(有注释):
- #导入库
- import matplotlib.pyplot as plt
- import seaborn as sns
-
- # 示例数据
- data = [50, 60, 70, 80, 90, 100, 66, 85, 90, 79, 85, 140,-5,5]
- plt.figure(figsize=(15,6))#创建图形,设置图形的尺寸
- sns.set(font='SimHei')#设置显示中文字符,解决Seaborn中文显示问题
-
- sns.boxplot(data)#用于绘制箱线图的数据为data
-
- plt.tick_params(labelsize=20) #刻度字体大小20
-
- plt.show()#画图
结果:
从上面的箱线图我们可以看到,有三个离群点,其中两个在最下值下方,有一个超过了最大值。
上面的箱线图是呈水平绘制的,如果想让它旋转90°,竖直呈现呢?代码如下:
代码(有注释):
- #导入库
- import matplotlib.pyplot as plt
- import seaborn as sns
-
- # 示例数据
- data = [50, 60, 70, 80, 90, 100, 66, 85, 90, 79, 85, 140,-5,5]
- plt.figure(figsize=(15,6))#创建图形,设置图形的尺寸
- sns.set(font='SimHei')#设置显示中文字符,解决Seaborn中文显示问题
-
- sns.boxplot(y=data)#用于绘制箱线图的数据为data
-
- plt.tick_params(labelsize=20) #刻度字体大小20
- plt.xlabel("2023年",fontsize=18)
- plt.ylabel("分数",fontsize=18)
- plt.show()#画图
这里代码只做了一个小调整,原先是sns.boxplot(data),现在把它改为sns.boxplot(y=data)即可。
结果:
这样箱线图就是我们想要的竖直呈现了
但是这个箱线图的宽度太宽了,如果想调整一下宽度,并且将表示中位数的这条线改为其它的颜色(如红色),并在图中表示出均值位置,怎样设置呢?
请看下边
代码:
- #导入库
- import matplotlib.pyplot as plt
- import seaborn as sns
- # 示例数据
- data = [50, 60, 70, 80, 90, 100, 66, 85, 90, 79, 85, 140,-5,5]
- plt.figure(figsize=(5,5))
- sns.set(font='SimHei')#设置显示中文字符,解决Seaborn中文显示问题
- # # 设置风格
- # sns.set(style="whitegrid")
- #medianprops={'color': 'red'}设置中位线为红色,showmeans=True控制使得否显示均值
- sns.boxplot(y=data,width=0.3,medianprops={'color': 'red'},showmeans=True,
- meanprops={'markerfacecolor': 'yellow', 'markeredgecolor': 'black'})
- plt.xlabel("2023",fontsize=18)
- plt.ylabel("分数",fontsize=18)
- plt.tick_params(labelsize=15) #刻度字体大小20
- plt.show()
解释:
①如上的代码,在下面的部分进行了改动,其中
- sns.boxplot(y=data,width=0.3,medianprops={'color': 'red'},showmeans=True,
- meanprops={'markerfacecolor': 'yellow', 'markeredgecolor': 'black'})
(1)width=0.3:调整箱线图的宽度,如下箱线图明显比原始箱线图窄了一些,美观了一些
(2)medianprops={'color': 'red'}:将表示中位数的线调成了红色,小伙伴可以自己调一下其他颜色试试
(3)showmeans=True:代表在箱线图中显示均值,其中均值是用一个小三角形来表示(如下图)
(4)meanprops={'markerfacecolor': 'yellow', 'markeredgecolor': 'green'}:表示均值的小三角形,内部用yellow黄色填充,外部轮廓是black,黑色
②同时也调整了图形的大小(长和宽),如下:
plt.figure(figsize=(5,5))
结果:
同时绘制如下多组数据的箱线图
数据有两列,
第一列是"年份",有三年,分别是2021、2022、2023年
第二列是”分数“
年份 | 分数 |
2021 | 150 |
2021 | 60 |
2021 | 70 |
2021 | 80 |
2021 | 90 |
2021 | 100 |
2021 | 56 |
2021 | 54 |
2021 | 85 |
2021 | 95 |
2021 | 62 |
2021 | -5 |
2021 | 10 |
2021 | 95 |
2021 | 85 |
2022 | 50 |
2022 | 60 |
2022 | 70 |
2022 | 80 |
2022 | 90 |
2022 | 100 |
2022 | -1 |
2022 | 54 |
2022 | 85 |
2022 | 95 |
2022 | 62 |
2022 | 100 |
2022 | 10 |
2022 | 95 |
2022 | 85 |
2023 | 80 |
2023 | 60 |
2023 | 70 |
2023 | 80 |
2023 | 90 |
2023 | 100 |
2023 | 56 |
2023 | 54 |
2023 | 85 |
2023 | 95 |
2023 | 62 |
2023 | 120 |
2023 | 10 |
2023 | 95 |
2023 | 85 |
- #导入库
- import matplotlib.pyplot as plt
- import seaborn as sns
- import pandas as pd
-
- #导入数据
- data=pd.read_excel("C:\\Users\\86159\Desktop\\CSDN\\箱线图数据.xlsx")
-
- #创建图例
- plt.figure(figsize=(15,6))
-
- #设置显示中文字符,解决Seaborn中文显示问题
- sns.set(font='SimHei')
-
- #medianprops={'color': 'red'}设置中位线为红色,showmeans=True控制使得否显示均值
- sns.boxplot(x=data["年份"],y=data["分数"],width=0.5,medianprops={'color': 'red'},showmeans=True,
- meanprops={'markerfacecolor': 'yellow', 'markeredgecolor': 'red'})
- #X轴标题
- plt.xlabel("年份",fontsize=18)
-
- #Y轴标签
- plt.ylabel("总分",fontsize=18)
-
- plt.tick_params(labelsize=15) #刻度字体大小20
-
- #画图
- plt.show()
导入的数据有两列,
第一列是"年份",有三年,分别是2021、2022、2023年
第二列是”分数“
代码有改动的部分如下:x=data["年份"],y=data["分数"],其它和原先设置的一样
- sns.boxplot(x=data["年份"],y=data["分数"],width=0.5,medianprops={'color': 'red'},showmeans=True,
- meanprops={'markerfacecolor': 'yellow', 'markeredgecolor': 'red'})
可以看到利用箱线图来判断离群点的话,2021年有两个离群点,2022年有一个离群点,2023年有一个离群点
补充:这组数据里有2021、2022、2023三年数据,如果只想画其中一年的箱线图,如2021年怎么办?如下:
- #导入库
- import matplotlib.pyplot as plt
- import seaborn as sns
-
-
- plt.figure(figsize=(15,6))#创建图例
- sns.set(font='SimHei')#设置显示中文字符,解决Seaborn中文显示问题
-
- sns.boxplot(x=data[data["年份"]==2021]["年份"],y=data[data["年份"]==2021]["分数"],width=0.5,medianprops={'color': 'red'},showmeans=True,
- meanprops={'markerfacecolor': 'yellow', 'markeredgecolor': 'red'})
-
- plt.xlabel("年份",fontsize=18)
- plt.ylabel("总分",fontsize=18)
- plt.tick_params(labelsize=15) #刻度字体大小20
- plt.show()
求Z-score分数,设置一个阈值,超过阈值的Z-score分数对应的原始数据为异常值。
- #导入库
- import pandas as pd
- import numpy as np
- from scipy import stats
-
- # 计算Z分数
- z_scores = np.abs(stats.zscore(data["分数"]))
-
- # 设置离群点阈值
- threshold = 2
-
- # 找到离群点的位置
- outliers = data[(z_scores > threshold)]
- print(outliers)
下图就是输出的判断为缺失值的数据
这样计算出来的离群点即包括了超过最大值的离群点,又包括了超过最小值的离群点,
是因为在计算Z分数时使用了绝对值函数(np.abs)。这意味着离群点的Z分数会被转换为正数,因此大于阈值的离群点也会被包含在内。
注:设置不同的阈值threshold,输出的离群点个数就会有所不同,这里阈值threshold=2,小伙伴可以自己改一下阈值,看一下结果。
从上图我们可以看出,一共输出了六个离群点,
2021年3个(箱线图中呈现了2个离群点,多了一个离群点),
2022年2个(箱线图中呈现了1个离群点,多了一个离群点),
2023年1个(符合上面的箱线图结果)。
如果就想准确找到箱线图中对应的离群点位置呢?请看下边
2021年:
- import pandas as pd
- import numpy as np
- from scipy import stats
-
-
- # 计算Z分数
- z_scores = np.abs(stats.zscore(data[data["年份"]==2021]["分数"]))
-
- # 设置离群点阈值
- threshold = 2
-
- # 找到离群点的位置
- outliers = data[data["年份"]==2021][(z_scores > threshold)]
- print(outliers)
其中data[data["年份"]==2021]就是整体数据中2021部分的数据
结果,如下,正好是对应2021年箱线图的两个离群点
2022年:
- import pandas as pd
- import numpy as np
- from scipy import stats
-
-
- # 计算Z分数
- z_scores = np.abs(stats.zscore(data[data["年份"]==2022]["分数"]))
-
- # 设置离群点阈值
- threshold = 2
-
- # 找到离群点的位置
- outliers = data[data["年份"]==2022][(z_scores > threshold)]
- print(outliers)
其中data[data["年份"]==2022]就是整体数据中2022部分的数据
结果,如下,正好是对应2022年箱线图的一个离群点
- # 生成一组有离群点的数据
- np.random.seed(0)
- data = np.concatenate([np.random.normal(0, 1, 50), [10, -10, 20]])
这两行代码的意思是将两个数组合并成一个。
首先,`np.random.normal(0, 1, 50)` 生成了一个包含50个服从均值为0、标准差为1的正态分布随机数的数组。
然后,`[10, -10, 20]` 是一个包含三个元素的列表。
最后,`np.concatenate([np.random.normal(0, 1, 50), [10, -10, 20]])` 使用 `np.concatenate()` 函数将这两个数组合并成一个。
最终得到的是由53个元素的数据,其中10,-10,20为离群点。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。