当前位置:   article > 正文

(代码详解)绘制箱线图+找离群点的具体位置+同时绘制多组数据的箱线图_用python绘制箱线图代码

用python绘制箱线图代码

       箱线图,是一种专门用于显示一组数据分散情况的统计图,通常呈现出一个箱子的形状。这种图形的主要作用是反映原始数据的分布特征,以及进行多组数据分布特征的比较。

      每一个箱子都包含一些关键的数学统计量,比如中位数、上四分位数(Q3)、下四分位数(Q1)、最大值、最小值等,它们共同揭示了数据的中心位置和散布范围。这些信息不仅能分析不同类别数据各层次水平的差异,还能揭示数据间的离散程度、异常值、以及分布差异等信息。

      在python中可以使用`matplotlib`和`seaborn`第三方库,来绘制箱线图

两种方法的区别

      使用 Matplotlib 库中的 pyplot 模块绘制箱线图。它提供了基本的箱线图功能,但可能不如其他专门针对数据可视化的库(如 Seaborn)那么美观和易用。

      使用 Seaborn 库绘制箱线图。Seaborn 是一个基于 Matplotlib 的数据可视化库,它提供了更高级的绘图功能,如更美观的样式、颜色映射等。使用 Seaborn 绘制箱线图可以使图形更加美观和易于理解。

     总结:如果你需要一个简单的箱线图,可以使用Matplotlib ;如果你希望获得更好的视觉效果和更丰富的功能,可以使用 Seaborn。

下面来介绍一下使用Seaborn如何绘制箱线图

(一)基础箱线图

代码(有注释):

  1. #导入库
  2. import matplotlib.pyplot as plt
  3. import seaborn as sns
  4. # 示例数据
  5. data = [50, 60, 70, 80, 90, 100, 66, 85, 90, 79, 85, 140,-5,5]
  6. plt.figure(figsize=(15,6))#创建图形,设置图形的尺寸
  7. sns.set(font='SimHei')#设置显示中文字符,解决Seaborn中文显示问题
  8. sns.boxplot(data)#用于绘制箱线图的数据为data
  9. plt.tick_params(labelsize=20) #刻度字体大小20
  10. plt.show()#画图

结果:

       从上面的箱线图我们可以看到,有三个离群点,其中两个在最下值下方,有一个超过了最大值。

     上面的箱线图是呈水平绘制的,如果想让它旋转90°,竖直呈现呢?代码如下:

代码(有注释):

  1. #导入库
  2. import matplotlib.pyplot as plt
  3. import seaborn as sns
  4. # 示例数据
  5. data = [50, 60, 70, 80, 90, 100, 66, 85, 90, 79, 85, 140,-5,5]
  6. plt.figure(figsize=(15,6))#创建图形,设置图形的尺寸
  7. sns.set(font='SimHei')#设置显示中文字符,解决Seaborn中文显示问题
  8. sns.boxplot(y=data)#用于绘制箱线图的数据为data
  9. plt.tick_params(labelsize=20) #刻度字体大小20
  10. plt.xlabel("2023年",fontsize=18)
  11. plt.ylabel("分数",fontsize=18)
  12. plt.show()#画图

这里代码只做了一个小调整,原先是sns.boxplot(data),现在把它改为sns.boxplot(y=data)即可。

结果:

     这样箱线图就是我们想要的竖直呈现了

     但是这个箱线图的宽度太宽了,如果想调整一下宽度,并且将表示中位数的这条线改为其它的颜色(如红色),并在图中表示出均值位置,怎样设置呢?

     请看下边

(二)调整箱线图参数设置

代码:

  1. #导入库
  2. import matplotlib.pyplot as plt
  3. import seaborn as sns
  4. # 示例数据
  5. data = [50, 60, 70, 80, 90, 100, 66, 85, 90, 79, 85, 140,-5,5]
  6. plt.figure(figsize=(5,5))
  7. sns.set(font='SimHei')#设置显示中文字符,解决Seaborn中文显示问题
  8. # # 设置风格
  9. # sns.set(style="whitegrid")
  10. #medianprops={'color': 'red'}设置中位线为红色,showmeans=True控制使得否显示均值
  11. sns.boxplot(y=data,width=0.3,medianprops={'color': 'red'},showmeans=True,
  12. meanprops={'markerfacecolor': 'yellow', 'markeredgecolor': 'black'})
  13. plt.xlabel("2023",fontsize=18)
  14. plt.ylabel("分数",fontsize=18)
  15. plt.tick_params(labelsize=15) #刻度字体大小20
  16. plt.show()

解释:

①如上的代码,在下面的部分进行了改动,其中

  1. sns.boxplot(y=data,width=0.3,medianprops={'color': 'red'},showmeans=True,
  2. 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))

结果:

 (三)绘制多组数据的箱线图

    (1)目的:

    同时绘制如下多组数据的箱线图

    (2)数据:

    数据有两列,

    第一列是"年份",有三年,分别是2021、2022、2023年

    第二列是”分数“

年份分数
2021150
202160
202170
202180
202190
2021100
202156
202154
202185
202195
202162
2021-5
202110
202195
202185
202250
202260
202270
202280
202290
2022100
2022-1
202254
202285
202295
202262
2022100
202210
202295
202285
202380
202360
202370
202380
202390
2023100
202356
202354
202385
202395
202362
2023120
202310
202395
202385
    (3)代码:
  1. #导入库
  2. import matplotlib.pyplot as plt
  3. import seaborn as sns
  4. import pandas as pd
  5. #导入数据
  6. data=pd.read_excel("C:\\Users\\86159\Desktop\\CSDN\\箱线图数据.xlsx")
  7. #创建图例
  8. plt.figure(figsize=(15,6))
  9. #设置显示中文字符,解决Seaborn中文显示问题
  10. sns.set(font='SimHei')
  11. #medianprops={'color': 'red'}设置中位线为红色,showmeans=True控制使得否显示均值
  12. sns.boxplot(x=data["年份"],y=data["分数"],width=0.5,medianprops={'color': 'red'},showmeans=True,
  13. meanprops={'markerfacecolor': 'yellow', 'markeredgecolor': 'red'})
  14. #X轴标题
  15. plt.xlabel("年份",fontsize=18)
  16. #Y轴标签
  17. plt.ylabel("总分",fontsize=18)
  18. plt.tick_params(labelsize=15) #刻度字体大小20
  19. #画图
  20. plt.show()
  (4)解释:

  导入的数据有两列,

  第一列是"年份",有三年,分别是2021、2022、2023年

  第二列是”分数“

  代码有改动的部分如下:x=data["年份"],y=data["分数"],其它和原先设置的一样

  1. sns.boxplot(x=data["年份"],y=data["分数"],width=0.5,medianprops={'color': 'red'},showmeans=True,
  2. meanprops={'markerfacecolor': 'yellow', 'markeredgecolor': 'red'})
  (5)结果:

       可以看到利用箱线图来判断离群点的话,2021年有两个离群点,2022年有一个离群点,2023年有一个离群点

补充:这组数据里有2021、2022、2023三年数据,如果只想画其中一年的箱线图,如2021年怎么办?如下:

  1. #导入库
  2. import matplotlib.pyplot as plt
  3. import seaborn as sns
  4. plt.figure(figsize=(15,6))#创建图例
  5. sns.set(font='SimHei')#设置显示中文字符,解决Seaborn中文显示问题
  6. sns.boxplot(x=data[data["年份"]==2021]["年份"],y=data[data["年份"]==2021]["分数"],width=0.5,medianprops={'color': 'red'},showmeans=True,
  7. meanprops={'markerfacecolor': 'yellow', 'markeredgecolor': 'red'})
  8. plt.xlabel("年份",fontsize=18)
  9. plt.ylabel("总分",fontsize=18)
  10. plt.tick_params(labelsize=15) #刻度字体大小20
  11. plt.show()

(四)找离群点的具体位置

思路:

求Z-score分数,设置一个阈值,超过阈值的Z-score分数对应的原始数据为异常值。

代码:
  1. #导入库
  2. import pandas as pd
  3. import numpy as np
  4. from scipy import stats
  5. # 计算Z分数
  6. z_scores = np.abs(stats.zscore(data["分数"]))
  7. # 设置离群点阈值
  8. threshold = 2
  9. # 找到离群点的位置
  10. outliers = data[(z_scores > threshold)]
  11. print(outliers)
结果:

   下图就是输出的判断为缺失值的数据

这样计算出来的离群点即包括了超过最大值的离群点,又包括了超过最小值的离群点,

是因为在计算Z分数时使用了绝对值函数(np.abs)。这意味着离群点的Z分数会被转换为正数,因此大于阈值的离群点也会被包含在内。

       注:设置不同的阈值threshold,输出的离群点个数就会有所不同,这里阈值threshold=2,小伙伴可以自己改一下阈值,看一下结果。

从上图我们可以看出,一共输出了六个离群点,

2021年3个(箱线图中呈现了2个离群点,多了一个离群点),

2022年2个(箱线图中呈现了1个离群点,多了一个离群点),

2023年1个(符合上面的箱线图结果)。

如果就想准确找到箱线图中对应的离群点位置呢?请看下边

2021年:

  1. import pandas as pd
  2. import numpy as np
  3. from scipy import stats
  4. # 计算Z分数
  5. z_scores = np.abs(stats.zscore(data[data["年份"]==2021]["分数"]))
  6. # 设置离群点阈值
  7. threshold = 2
  8. # 找到离群点的位置
  9. outliers = data[data["年份"]==2021][(z_scores > threshold)]
  10. print(outliers)

其中data[data["年份"]==2021]就是整体数据中2021部分的数据

结果,如下,正好是对应2021年箱线图的两个离群点

2022年:

  1. import pandas as pd
  2. import numpy as np
  3. from scipy import stats
  4. # 计算Z分数
  5. z_scores = np.abs(stats.zscore(data[data["年份"]==2022]["分数"]))
  6. # 设置离群点阈值
  7. threshold = 2
  8. # 找到离群点的位置
  9. outliers = data[data["年份"]==2022][(z_scores > threshold)]
  10. print(outliers)

其中data[data["年份"]==2022]就是整体数据中2022部分的数据

结果,如下,正好是对应2022年箱线图的一个离群点

(五)随机生成一组离群点数据

  1. # 生成一组有离群点的数据
  2. np.random.seed(0)
  3. 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为离群点。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/612049
推荐阅读
相关标签
  

闽ICP备14008679号