Matplotlib中violinplot()和boxplot()的区别与应用

Matplotlib中violinplot()和boxplot()的区别与应用

参考:How is violinplot() Different from boxplot()

Matplotlib是Python中最流行的数据可视化库之一,它提供了多种绘图工具来展示数据分布。其中,violinplot()和boxplot()是两种常用的统计图表类型,用于展示数据的分布情况。虽然这两种图表都能展示数据的分布特征,但它们在表现形式和信息呈现上有着显著的差异。本文将深入探讨violinplot()和boxplot()的区别,并通过实例演示它们的使用方法和适用场景。

1. boxplot()简介

boxplot(),也称为箱线图,是一种用于显示一组数据分散情况的统计图表。它以一种相对简洁的方式展示了数据的五个数字概括(最小值、第一四分位数、中位数、第三四分位数和最大值),同时还可以显示异常值。

1.1 boxplot()的基本组成

一个典型的箱线图包含以下几个部分:

  1. 箱体:代表数据的中间50%,即从第一四分位数(Q1)到第三四分位数(Q3)的范围。
  2. 中位线:在箱体内部的一条线,表示数据的中位数。
  3. 须线:从箱体延伸出去的线,通常延伸到最小值和最大值,但不包括异常值。
  4. 异常值:通常以单独的点表示,位于须线之外。

让我们通过一个简单的例子来看看如何使用Matplotlib绘制箱线图:

import matplotlib.pyplot as plt
import numpy as np

# 生成示例数据
np.random.seed(42)
data = [np.random.normal(0, std, 100) for std in range(1, 4)]

# 创建箱线图
fig, ax = plt.subplots()
ax.boxplot(data)

# 设置标题和标签
ax.set_title('Boxplot Example - how2matplotlib.com')
ax.set_xlabel('Groups')
ax.set_ylabel('Values')

plt.show()

Output:

Matplotlib中violinplot()和boxplot()的区别与应用

在这个例子中,我们生成了三组正态分布的数据,并使用boxplot()函数绘制了箱线图。每个箱体代表一组数据的分布情况。

1.2 boxplot()的优势

  1. 简洁明了:箱线图能够以一种简洁的方式展示数据的关键统计特征。
  2. 易于比较:当需要比较多个数据集时,箱线图可以并排放置,方便直观比较。
  3. 异常值识别:箱线图可以清晰地显示数据中的异常值。
  4. 数据偏斜度:通过观察箱体的形状和位置,可以快速判断数据的偏斜程度。

1.3 boxplot()的局限性

  1. 信息损失:箱线图只显示五个关键统计量,可能会丢失一些细节信息。
  2. 无法显示多峰分布:如果数据存在多个峰值,箱线图无法直观地表现出来。
  3. 样本量不明确:从箱线图中无法直接看出样本的数量。

2. violinplot()简介

violinplot(),也称为小提琴图,是一种结合了箱线图和核密度图特点的统计图表。它不仅展示了数据的概括统计信息,还能显示数据的概率密度。

2.1 violinplot()的基本组成

一个典型的小提琴图包含以下几个部分:

  1. 密度轮廓:表示数据的概率密度分布,形状类似小提琴。
  2. 中位数:通常用一个点或线表示。
  3. 四分位数范围:可以在密度轮廓内部用线段表示。
  4. 最大值和最小值:可以用线段的端点表示。

下面是一个使用Matplotlib绘制小提琴图的例子:

import matplotlib.pyplot as plt
import numpy as np

# 生成示例数据
np.random.seed(42)
data = [np.random.normal(0, std, 100) for std in range(1, 4)]

# 创建小提琴图
fig, ax = plt.subplots()
ax.violinplot(data)

# 设置标题和标签
ax.set_title('Violinplot Example - how2matplotlib.com')
ax.set_xlabel('Groups')
ax.set_ylabel('Values')

plt.show()

Output:

Matplotlib中violinplot()和boxplot()的区别与应用

在这个例子中,我们使用了与箱线图相同的数据,但使用violinplot()函数来绘制小提琴图。每个”小提琴”代表一组数据的分布情况。

2.2 violinplot()的优势

  1. 详细的分布信息:小提琴图能够显示数据的完整概率密度分布。
  2. 多峰分布可视化:可以清晰地展示数据中的多个峰值。
  3. 直观比较:可以方便地比较不同组之间的分布差异。
  4. 美观性:小提琴图的形状通常比箱线图更加美观,更能吸引读者的注意力。

2.3 violinplot()的局限性

  1. 复杂性:相比箱线图,小提琴图可能需要更多的解释才能被完全理解。
  2. 计算密集:绘制小提琴图需要计算核密度估计,对于大型数据集可能会比较耗时。
  3. 样本量不明确:与箱线图类似,小提琴图也无法直接反映样本量的大小。

3. violinplot()和boxplot()的主要区别

3.1 数据表现形式

  • boxplot():主要展示数据的五个数字概括(最小值、第一四分位数、中位数、第三四分位数和最大值)。
  • violinplot():除了显示这些统计量外,还展示了完整的概率密度分布。

让我们通过一个例子来直观比较这两种图表:

import matplotlib.pyplot as plt
import numpy as np

# 生成示例数据
np.random.seed(42)
data1 = np.random.normal(0, 1, 200)
data2 = np.concatenate([np.random.normal(-1, 0.5, 100), np.random.normal(1, 0.5, 100)])

# 创建子图
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6))

# 绘制箱线图
ax1.boxplot([data1, data2])
ax1.set_title('Boxplot - how2matplotlib.com')
ax1.set_xlabel('Groups')
ax1.set_ylabel('Values')

# 绘制小提琴图
ax2.violinplot([data1, data2])
ax2.set_title('Violinplot - how2matplotlib.com')
ax2.set_xlabel('Groups')
ax2.set_ylabel('Values')

plt.tight_layout()
plt.show()

Output:

Matplotlib中violinplot()和boxplot()的区别与应用

在这个例子中,我们生成了两组数据:data1是一个单峰的正态分布,data2是一个双峰分布。通过比较,我们可以看到小提琴图更清晰地展示了data2的双峰特性,而箱线图则无法显示这一特征。

3.2 数据密度表现

  • boxplot():不直接显示数据密度信息。
  • violinplot():通过形状的宽度直观地表现数据密度。

以下示例展示了如何使用violinplot()来显示数据密度:

import matplotlib.pyplot as plt
import numpy as np

# 生成示例数据
np.random.seed(42)
data = [np.random.normal(0, std, 1000) for std in range(1, 5)]

# 创建小提琴图
fig, ax = plt.subplots()
ax.violinplot(data, showmeans=True, showmedians=True)

# 设置标题和标签
ax.set_title('Violinplot with Density - how2matplotlib.com')
ax.set_xlabel('Groups')
ax.set_ylabel('Values')

plt.show()

Output:

Matplotlib中violinplot()和boxplot()的区别与应用

在这个例子中,小提琴图的宽度反映了数据在不同值上的密度。较宽的部分表示数据在该区域更为集中。

3.3 异常值处理

  • boxplot():通常将异常值作为单独的点显示在图上。
  • violinplot():默认情况下不显示异常值,但可以通过参数设置来显示。

下面的例子展示了如何在boxplot和violinplot中处理异常值:

import matplotlib.pyplot as plt
import numpy as np

# 生成示例数据(包含异常值)
np.random.seed(42)
data = np.random.normal(0, 1, 100)
data = np.append(data, [5, -5])  # 添加异常值

# 创建子图
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6))

# 绘制箱线图
ax1.boxplot(data)
ax1.set_title('Boxplot with Outliers - how2matplotlib.com')
ax1.set_ylabel('Values')

# 绘制小提琴图
ax2.violinplot(data, showextrema=True)
ax2.set_title('Violinplot with Extrema - how2matplotlib.com')
ax2.set_ylabel('Values')

plt.tight_layout()
plt.show()

Output:

Matplotlib中violinplot()和boxplot()的区别与应用

在这个例子中,箱线图清晰地显示了异常值,而小提琴图则通过showextrema参数显示了极值。

3.4 多组数据比较

both boxplot()和violinplot()都适合用于多组数据的比较,但它们在视觉表现上有所不同:

import matplotlib.pyplot as plt
import numpy as np

# 生成示例数据
np.random.seed(42)
data = [np.random.normal(i, 1, 100) for i in range(5)]

# 创建子图
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6))

# 绘制箱线图
ax1.boxplot(data)
ax1.set_title('Boxplot Comparison - how2matplotlib.com')
ax1.set_xlabel('Groups')
ax1.set_ylabel('Values')

# 绘制小提琴图
ax2.violinplot(data)
ax2.set_title('Violinplot Comparison - how2matplotlib.com')
ax2.set_xlabel('Groups')
ax2.set_ylabel('Values')

plt.tight_layout()
plt.show()

Output:

Matplotlib中violinplot()和boxplot()的区别与应用

在这个例子中,我们可以看到boxplot和violinplot在比较多组数据时的不同表现。violinplot能够更直观地显示每组数据的分布形状。

4. 何时选择violinplot()或boxplot()

选择使用violinplot()还是boxplot()主要取决于你的数据特征和你想要传达的信息。以下是一些指导原则:

4.1 选择boxplot()的情况

  1. 当你主要关注数据的中心趋势和离散程度时。
  2. 当你需要清晰地展示异常值时。
  3. 当你的受众更熟悉箱线图的解读方式时。
  4. 当你需要一个简洁、快速的数据概览时。

4.2 选择violinplot()的情况

  1. 当你想要展示完整的数据分布形状时。
  2. 当你的数据可能存在多峰分布时。
  3. 当你需要比较不同组之间的概率密度分布时。
  4. 当你想要一个视觉上更吸引人的图表时。

4.3 结合使用的情况

有时候,同时使用boxplot()和violinplot()可以提供更全面的数据视图。例如:

import matplotlib.pyplot as plt
import numpy as np

# 生成示例数据
np.random.seed(42)
data1 = np.random.normal(0, 1, 200)
data2 = np.concatenate([np.random.normal(-1, 0.5, 100), np.random.normal(1, 0.5, 100)])

# 创建图表
fig, ax = plt.subplots(figsize=(10, 6))

# 绘制小提琴图
parts = ax.violinplot([data1, data2], showmeans=False, showmedians=False)

# 设置小提琴图的颜色
colors = ['lightblue', 'lightgreen']
for pc, color in zip(parts['bodies'], colors):
    pc.set_facecolor(color)
    pc.set_edgecolor('black')
    pc.set_alpha(0.7)

# 添加箱线图
ax.boxplot([data1, data2], positions=[1, 2], widths=0.15, patch_artist=True,
           showfliers=False, medianprops={"color": "white", "linewidth": 0.5},
           boxprops={"facecolor": "white", "edgecolor": "black", "alpha": 0.5})

# 设置标题和标签
ax.set_title('Combined Violin and Box Plot - how2matplotlib.com')
ax.set_xlabel('Groups')
ax.set_ylabel('Values')

plt.show()

Output:

Matplotlib中violinplot()和boxplot()的区别与应用

在这个例子中,我们将小提琴图和箱线图结合在一起,既展示了完整的数据分布,又突出了关键的统计量。

5. violinplot()和boxplot()的高级用法

5.1 自定义boxplot()

Matplotlib允许我们对箱线图进行各种自定义,以更好地适应特定的数据可视化需求。以下是一个自定义boxplot()的示例:

import matplotlib.pyplot as plt
import numpy as np

# 生成示例数据
np.random.seed(42)
data = [np.random.normal(0, std, 100) for std in range(1, 5)]

# 创建箱线图
fig, ax = plt.subplots()
bp = ax.boxplot(data, patch_artist=True)

# 自定义颜色
colors = ['lightblue', 'lightgreen', 'tan', 'pink']
for patch, color in zip(bp['boxes'], colors):
    patch.set_facecolor(color)

# 自定义中位数线
for median in bp['medians']:
    median.set_color('red')
    median.set_linewidth(2)

# 自定义须线
for whisker in bp['whiskers']:
    whisker.set_color('gray')
    whisker.set_linestyle('--')

# 设置标题和标签
ax.set_title('Customized Boxplot - how2matplotlib.com')
ax.set_xlabel('Groups')
ax.set_ylabel('Values')

plt.show()

Output:

Matplotlib中violinplot()和boxplot()的区别与应用

在这个例子中,我们自定义了箱体的颜色、中位数线的样式以及须线的外观,使得箱线图更加美观和信息丰富。

5.2 自定义violinplot()

同样,我们也可以自定义violinplot()来增强其表现力:

import matplotlib.pyplot as plt
import numpy as np

# 生成示例数据
np.random.seed(42)
data = [np.random.normal(0, std, 100) for std in range(1, 5)]

# 创建小提琴图
fig, ax = plt.subplots()
parts = ax.violinplot(data, showmeans=False, showextrema=False, showmedians=False)

# 自定义颜色和透明度
colors = ['lightblue', 'lightgreen', 'tan', 'pink']
for i, pc in enumerate(parts['bodies']):
    pc.set_facecolor(colors[i])
    pc.set_edgecolor('black')
    pc.set_alpha(0.7)

# 添加均值点
means = [np.mean(d) for d in data]
ax.scatter(range(1, len(data) + 1), means, marker='o', color='white', s=30, zorder=3)

# 添加中位数线
medians = [np.median(d) for d in data]
ax.vlines(range(1, len(data) + 1), [np.min(d) for d in data], [np.max(d) for d in data], color='k', linestyle='-', lw=1)
ax.scatter(range(1, len(data) + 1), medians, marker='o', color='white', s=30, zorder=3)

# 设置标题和标签
ax.set_title('Customized Violinplot - how2matplotlib.com')
ax.set_xlabel('Groups')
ax.set_ylabel('Values')

plt.show()

Output:

Matplotlib中violinplot()和boxplot()的区别与应用

在这个例子中,我们自定义了小提琴图的颜色和透明度,并添加了均值点和中位数线,使得图表更加丰富和直观。

6. violinplot()和boxplot()的组合应用

有时候,将violinplot()和boxplot()结合使用可以提供更全面的数据视图。以下是一个组合应用的示例:

import matplotlib.pyplot as plt
import numpy as np

# 生成示例数据
np.random.seed(42)
data1 = np.random.normal(0, 1, 200)
data2 = np.concatenate([np.random.normal(-1, 0.5, 100), np.random.normal(1, 0.5, 100)])
data = [data1, data2]

# 创建图表
fig, ax = plt.subplots(figsize=(10, 6))

# 绘制小提琴图
parts = ax.violinplot(data, showmeans=False, showmedians=False)

# 设置小提琴图的颜色
colors = ['lightblue', 'lightgreen']
for i, pc in enumerate(parts['bodies']):
    pc.set_facecolor(colors[i])
    pc.set_edgecolor('black')
    pc.set_alpha(0.7)

# 添加箱线图
bp = ax.boxplot(data, positions=[1, 2], widths=0.15, patch_artist=True,
                showfliers=False, medianprops={"color": "white", "linewidth": 0.5},
                boxprops={"facecolor": "white", "edgecolor": "black", "alpha": 0.5})

# 设置标题和标签
ax.set_title('Combined Violin and Box Plot - how2matplotlib.com')
ax.set_xlabel('Groups')
ax.set_ylabel('Values')

plt.show()

Output:

Matplotlib中violinplot()和boxplot()的区别与应用

这个例子展示了如何将小提琴图和箱线图结合在一起,既展示了完整的数据分布,又突出了关键的统计量。

7. 在实际应用中选择合适的图表

在实际应用中,选择使用violinplot()还是boxplot()(或两者结合)主要取决于以下因素:

  1. 数据特征:如果数据分布复杂(如多峰分布),violinplot()可能更合适;如果主要关注中心趋势和离散程度,boxplot()可能足够。

  2. 受众:考虑你的目标受众是否熟悉这些图表类型。boxplot()通常更为常见和易于理解。

  3. 展示目的:如果需要详细展示数据分布的形状,选择violinplot();如果需要突出显示异常值,boxplot()可能更合适。

  4. 数据量:对于大量数据集,violinplot()可能会提供更多信息,但计算成本也更高。

  5. 可视化空间:如果有限的空间需要展示多组数据,boxplot()可能更紧凑。

  6. 美观需求:如果追求更美观的可视化效果,violinplot()通常更具吸引力。

让我们通过一个实际应用的例子来说明如何选择合适的图表:

import matplotlib.pyplot as plt
import numpy as np

# 模拟某公司不同部门的工资数据
np.random.seed(42)
departments = ['HR', 'IT', 'Sales', 'Marketing', 'Finance']
salaries = [
    np.random.normal(50000, 5000, 100),  # HR
    np.concatenate([np.random.normal(60000, 5000, 50), np.random.normal(80000, 5000, 50)]),  # IT
    np.random.normal(55000, 10000, 100),  # Sales
    np.random.normal(52000, 7000, 100),  # Marketing
    np.random.lognormal(11, 0.2, 100)  # Finance
]

# 创建子图
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))

# 绘制箱线图
bp = ax1.boxplot(salaries, patch_artist=True)
ax1.set_xticklabels(departments)
ax1.set_title('Salary Distribution (Boxplot) - how2matplotlib.com')
ax1.set_ylabel('Salary ()')

# 自定义箱线图颜色
colors = ['lightblue', 'lightgreen', 'tan', 'pink', 'lightyellow']
for patch, color in zip(bp['boxes'], colors):
    patch.set_facecolor(color)

# 绘制小提琴图
vp = ax2.violinplot(salaries, showmeans=True, showmedians=True)
ax2.set_xticks(range(1, len(departments) + 1))
ax2.set_xticklabels(departments)
ax2.set_title('Salary Distribution (Violinplot) - how2matplotlib.com')
ax2.set_ylabel('Salary ()')

# 自定义小提琴图颜色
for i, pc in enumerate(vp['bodies']):
    pc.set_facecolor(colors[i])
    pc.set_edgecolor('black')
    pc.set_alpha(0.7)

plt.tight_layout()
plt.show()

Output:

Matplotlib中violinplot()和boxplot()的区别与应用

在这个例子中,我们模拟了一家公司不同部门的工资数据,并使用boxplot()和violinplot()来可视化这些数据。通过比较这两种图表,我们可以得出以下观察:

  1. boxplot()清晰地显示了每个部门工资的中位数、四分位数范围和异常值,适合快速比较各部门的工资水平和离散程度。

  2. violinplot()则更好地展示了工资分布的形状。例如,我们可以看到IT部门的工资分布呈现双峰特征,这在boxplot()中是无法直接观察到的。

  3. Finance部门的工资分布在violinplot()中显示为右偏分布,这一特征在boxplot()中不太明显。

  4. Sales部门的工资分布在violinplot()中显示为较宽的形状,表明工资差异较大,这一点在boxplot()中也可以通过较长的箱体看出。

  5. HR和Marketing部门的工资分布相对较为集中,这在两种图表中都有体现。

通过这个例子,我们可以看到violinplot()和boxplot()各有优势。在实际应用中,可以根据数据特征和展示需求选择合适的图表类型,或者像这个例子一样同时使用两种图表,以提供更全面的数据视图。

8. 结论

violinplot()和boxplot()都是强大的数据可视化工具,各有其优势和适用场景。boxplot()简洁明了,适合快速展示数据的中心趋势和离散程度,而violinplot()则能更详细地展示数据的分布形状。在实际应用中,应根据数据特征、分析目的和目标受众来选择合适的图表类型。有时候,结合使用这两种图表可以提供更全面的数据洞察。

无论选择哪种图表,关键是要确保图表能够清晰、准确地传达数据中的关键信息。通过合理的自定义和优化,我们可以使这些图表更具信息量和视觉吸引力,从而更好地支持数据分析和决策过程。

最后,建议读者在实际项目中多尝试使用这两种图表,并根据具体情况进行调整和优化,以找到最适合自己数据和需求的可视化方式。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程