Matplotlib 分组箱线图:全面掌握数据可视化技巧

Matplotlib 分组箱线图:全面掌握数据可视化技巧

参考:matplotlib boxplot by group

Matplotlib 是 Python 中最流行的数据可视化库之一,而箱线图(Boxplot)则是展示数据分布的有力工具。本文将深入探讨如何使用 Matplotlib 创建分组箱线图,帮助您更好地理解和呈现数据。我们将从基础概念开始,逐步深入到高级技巧,并提供丰富的示例代码,让您轻松掌握这一强大的数据可视化方法。

1. 箱线图基础

箱线图是一种用于显示一组数据分布情况的统计图,它可以直观地展示出数据的中位数、四分位数、异常值等重要统计信息。在开始创建分组箱线图之前,我们先来了解一下基本的箱线图。

以下是一个简单的箱线图示例:

import matplotlib.pyplot as plt
import numpy as np

# 生成示例数据
np.random.seed(42)
data = np.random.randn(100)

# 创建箱线图
plt.figure(figsize=(8, 6))
plt.boxplot(data)
plt.title('Basic Boxplot - how2matplotlib.com')
plt.ylabel('Values')
plt.show()

Output:

Matplotlib 分组箱线图:全面掌握数据可视化技巧

在这个例子中,我们使用 numpy 生成了一组随机数据,然后使用 plt.boxplot() 函数创建了一个基本的箱线图。箱线图显示了数据的中位数(箱子中的横线)、上下四分位数(箱子的上下边界)、最大最小值(须线的端点)以及可能的异常值(以点表示)。

2. 创建分组箱线图

分组箱线图允许我们在同一图表中比较多组数据的分布情况。这在比较不同类别或条件下的数据分布时特别有用。让我们看一个简单的分组箱线图示例:

import matplotlib.pyplot as plt
import numpy as np

# 生成示例数据
np.random.seed(42)
group1 = np.random.normal(0, 1, 100)
group2 = np.random.normal(2, 1.5, 100)
group3 = np.random.normal(-1, 2, 100)

# 创建分组箱线图
plt.figure(figsize=(10, 6))
plt.boxplot([group1, group2, group3], labels=['Group 1', 'Group 2', 'Group 3'])
plt.title('Grouped Boxplot - how2matplotlib.com')
plt.ylabel('Values')
plt.show()

Output:

Matplotlib 分组箱线图:全面掌握数据可视化技巧

在这个例子中,我们创建了三组具有不同分布特征的数据,然后将它们作为一个列表传递给 plt.boxplot() 函数。通过设置 labels 参数,我们为每个箱线图添加了标签。

3. 自定义箱线图样式

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)]

# 创建自定义样式的箱线图
plt.figure(figsize=(10, 6))
box_plot = plt.boxplot(data, patch_artist=True)

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

# 自定义其他元素
plt.title('Customized Boxplot - how2matplotlib.com')
plt.ylabel('Values')
plt.xlabel('Groups')
plt.xticks([1, 2, 3], ['Group A', 'Group B', 'Group C'])

plt.show()

Output:

Matplotlib 分组箱线图:全面掌握数据可视化技巧

在这个例子中,我们使用 patch_artist=True 参数来允许填充箱子。然后,我们通过遍历 box_plot['boxes'] 来设置每个箱子的填充颜色。我们还自定义了 x 轴的刻度标签。

4. 添加数据点

有时,除了箱线图本身,我们还想在图上显示原始数据点。这可以帮助我们更好地理解数据的分布。以下是一个在箱线图上添加数据点的示例:

import matplotlib.pyplot as plt
import numpy as np

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

# 创建带数据点的箱线图
plt.figure(figsize=(10, 6))
box_plot = plt.boxplot(data, patch_artist=True)

# 添加数据点
for i, d in enumerate(data):
    y = d
    x = np.random.normal(i+1, 0.04, len(y))
    plt.scatter(x, y, alpha=0.4)

plt.title('Boxplot with Data Points - how2matplotlib.com')
plt.ylabel('Values')
plt.xlabel('Groups')
plt.xticks([1, 2, 3], ['Group A', 'Group B', 'Group C'])

plt.show()

Output:

Matplotlib 分组箱线图:全面掌握数据可视化技巧

在这个例子中,我们使用 plt.scatter() 函数在每个箱线图旁边添加了散点图。为了避免点重叠,我们在 x 轴方向上添加了一些随机抖动。

5. 水平箱线图

默认情况下,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, 6)]

# 创建水平箱线图
plt.figure(figsize=(10, 8))
plt.boxplot(data, vert=False, labels=['A', 'B', 'C', 'D', 'E'])
plt.title('Horizontal Boxplot - how2matplotlib.com')
plt.xlabel('Values')
plt.ylabel('Groups')
plt.show()

Output:

Matplotlib 分组箱线图:全面掌握数据可视化技巧

在这个例子中,我们使用 vert=False 参数来创建水平方向的箱线图。注意,这时 xlabelylabel 的含义也相应地交换了。

6. 多列分组箱线图

当我们需要比较多个类别和子类别的数据时,多列分组箱线图就非常有用。以下是一个创建多列分组箱线图的示例:

import matplotlib.pyplot as plt
import numpy as np

# 生成示例数据
np.random.seed(42)
data = {
    'Group1': [np.random.normal(0, 1, 100), np.random.normal(2, 1, 100)],
    'Group2': [np.random.normal(1, 1.5, 100), np.random.normal(3, 1.5, 100)],
    'Group3': [np.random.normal(-1, 2, 100), np.random.normal(1, 2, 100)]
}

# 创建多列分组箱线图
fig, axes = plt.subplots(1, 3, figsize=(15, 6), sharey=True)
fig.suptitle('Multi-column Grouped Boxplot - how2matplotlib.com')

for ax, (group, group_data) in zip(axes, data.items()):
    ax.boxplot(group_data)
    ax.set_title(group)
    ax.set_xticklabels(['Subgroup A', 'Subgroup B'])
    ax.set_ylabel('Values')

plt.tight_layout()
plt.show()

Output:

Matplotlib 分组箱线图:全面掌握数据可视化技巧

在这个例子中,我们使用 plt.subplots() 创建了三个并排的子图,每个子图对应一个主要组别。然后,我们在每个子图中绘制该组的两个子组的箱线图。

7. 添加均值点

在箱线图中添加均值点可以提供额外的统计信息。以下是一个在箱线图上添加均值点的示例:

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(figsize=(10, 6))
box_plot = ax.boxplot(data)

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

ax.set_title('Boxplot with Mean Points - how2matplotlib.com')
ax.set_ylabel('Values')
ax.set_xticklabels(['Group A', 'Group B', 'Group C'])

plt.show()

Output:

Matplotlib 分组箱线图:全面掌握数据可视化技巧

在这个例子中,我们首先创建了常规的箱线图,然后使用 ax.scatter() 函数在每个箱子上方添加了表示均值的红点。

8. 使用 Seaborn 创建分组箱线图

虽然 Matplotlib 功能强大,但有时使用建立在 Matplotlib 之上的高级库如 Seaborn 可以更轻松地创建复杂的统计图表。以下是使用 Seaborn 创建分组箱线图的示例:

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np

# 生成示例数据
np.random.seed(42)
data = pd.DataFrame({
    'group': np.repeat(['A', 'B', 'C'], 100),
    'subgroup': np.tile(np.repeat(['X', 'Y'], 50), 3),
    'value': np.concatenate([
        np.random.normal(0, 1, 100),
        np.random.normal(2, 1, 100),
        np.random.normal(1, 1.5, 100)
    ])
})

# 创建 Seaborn 分组箱线图
plt.figure(figsize=(12, 6))
sns.boxplot(x='group', y='value', hue='subgroup', data=data)
plt.title('Seaborn Grouped Boxplot - how2matplotlib.com')
plt.show()

Output:

Matplotlib 分组箱线图:全面掌握数据可视化技巧

在这个例子中,我们首先创建了一个包含分组信息的 pandas DataFrame。然后,我们使用 Seaborn 的 boxplot() 函数创建了一个分组箱线图,其中 x 参数指定主要分组,y 参数指定数值,hue 参数指定子分组。

9. 箱线图与小提琴图的组合

小提琴图是箱线图的一个变体,它能更好地显示数据的分布密度。我们可以将箱线图和小提琴图结合起来,以提供更丰富的数据视图。以下是一个示例:

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np

# 生成示例数据
np.random.seed(42)
data = pd.DataFrame({
    'group': np.repeat(['A', 'B', 'C'], 200),
    'value': np.concatenate([
        np.random.normal(0, 1, 200),
        np.random.normal(2, 1.5, 200),
        np.random.gamma(2, 2, 200)
    ])
})

# 创建箱线图和小提琴图的组合
plt.figure(figsize=(12, 6))
sns.violinplot(x='group', y='value', data=data, inner='box')
plt.title('Violin Plot with Inner Boxplot - how2matplotlib.com')
plt.show()

Output:

Matplotlib 分组箱线图:全面掌握数据可视化技巧

在这个例子中,我们使用 Seaborn 的 violinplot() 函数创建了小提琴图,并通过设置 inner='box' 参数在小提琴图内部添加了箱线图。这种组合图能同时显示数据的分布密度和关键统计信息。

10. 动态更新的箱线图

在某些情况下,我们可能需要创建能够动态更新的箱线图,例如用于实时数据可视化。以下是一个简单的动态更新箱线图的示例:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.animation import FuncAnimation

# 初始化数据
data = [np.random.normal(0, 1, 100) for _ in range(3)]

# 创建图形和箱线图
fig, ax = plt.subplots(figsize=(10, 6))
box_plot = ax.boxplot(data)

ax.set_title('Dynamic Boxplot - how2matplotlib.com')
ax.set_ylabel('Values')
ax.set_xticklabels(['Group A', 'Group B', 'Group C'])

# 更新函数
def update(frame):
    # 更新数据
    for i in range(3):
        data[i] = np.random.normal(frame, 1, 100)

    # 更新箱线图
    for i, d in enumerate(data):
        box_plot['medians'][i].set_ydata([np.median(d), np.median(d)])
        box_plot['boxes'][i].set_ydata([np.percentile(d, 25), np.percentile(d, 75), np.percentile(d, 75), np.percentile(d, 25), np.percentile(d, 25)])
        box_plot['whiskers'][2*i].set_ydata([np.min(d), np.percentile(d, 25)])
        box_plot['whiskers'][2*i+1].set_ydata([np.percentile(d, 75), np.max(d)])
        box_plot['caps'][2*i].set_ydata([np.min(d), np.min(d)])
        box_plot['caps'][2*i+1].set_ydata([np.max(d), np.max(d)])

    return box_plot['boxes'] + box_plot['medians'] + box_plot['whiskers'] + box_plot['caps']

# 创建动画
anim = FuncAnimation(fig, update, frames=np.linspace(-3, 3, 100), interval=100, blit=True)
plt.show()

Output:

Matplotlib 分组箱线图:全面掌握数据可视化技巧

在这个例子中,我们创建了一个初始的箱线图,然后定义了一个 update 函数来动态更新数据和箱线图的各个组成部分。使用 FuncAnimation 函数,我们创建了一个动画,使箱线图随时间变化。

11. 带有统计检验的箱线图

在进行数据分析时,我们经常需要进行统计检验来确定组间差异是否显著。我们可以在箱线图上添加统计检验的结果,以提供更多信息。以下是一个使用 statannot 库在箱线图上添加统计检验结果的示例:

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
from statannot import add_stat_annotation

# 生成示例数据
np.random.seed(42)
data = pd.DataFrame({
    'group': np.repeat(['A', 'B', 'C'], 100),
    'value': np.concatenate([
        np.random.normal(0, 1, 100),
        np.random.normal(2, 1, 100),
        np.random.normal(1, 1.5, 100)
    ])
})

# 创建箱线图
plt.figure(figsize=(12, 6))
ax = sns.boxplot(x='group', y='value', data=data)

# 添加统计注释
add_stat_annotation(ax, data=data, x='group', y='value',
                    box_pairs=[('A', 'B'), ('B', 'C'), ('A', 'C')],
                    test='t-test_ind', text_format='star', loc='inside', verbose=2)

plt.title('Boxplot with Statistical Annotations - how2matplotlib.com')
plt.show()

在这个例子中,我们首先创建了一个基本的箱线图,然后使用 add_stat_annotation 函数添加了成对的 t 检验结果。统计显著性用星号表示,直接显示在箱线图上。

12. 多变量箱线图

当我们需要同时比较多个变量的分布时,多变量箱线图可能会很有用。以下是一个创建多变量箱线图的示例:

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np

# 生成示例数据
np.random.seed(42)
n = 200
data = pd.DataFrame({
    'group': np.repeat(['A', 'B'], n),
    'var1': np.concatenate([np.random.normal(0, 1, n), np.random.normal(2, 1, n)]),
    'var2': np.concatenate([np.random.normal(1, 1.5, n), np.random.normal(0, 1.5, n)]),
    'var3': np.concatenate([np.random.normal(-1, 2, n), np.random.normal(1, 2, n)])
})

# 将数据转换为长格式
data_long = pd.melt(data, id_vars=['group'], var_name='variable', value_name='value')

# 创建多变量箱线图
plt.figure(figsize=(12, 6))
sns.boxplot(x='variable', y='value', hue='group', data=data_long)
plt.title('Multivariate Boxplot - how2matplotlib.com')
plt.show()

Output:

Matplotlib 分组箱线图:全面掌握数据可视化技巧

在这个例子中,我们首先创建了一个包含多个变量的数据集,然后使用 pd.melt() 函数将数据转换为长格式。最后,我们使用 Seaborn 的 boxplot() 函数创建了一个多变量箱线图,其中 x 轴表示不同的变量,hue 参数用于区分不同的组。

13. 箱线图与散点图的组合

有时,我们可能希望在箱线图旁边显示原始数据点,以提供更详细的数据分布信息。以下是一个将箱线图与散点图结合的示例:

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np

# 生成示例数据
np.random.seed(42)
data = pd.DataFrame({
    'group': np.repeat(['A', 'B', 'C'], 100),
    'value': np.concatenate([
        np.random.normal(0, 1, 100),
        np.random.normal(2, 1, 100),
        np.random.normal(1, 1.5, 100)
    ])
})

# 创建箱线图和散点图的组合
plt.figure(figsize=(12, 6))
sns.boxplot(x='group', y='value', data=data, color='lightgray')
sns.stripplot(x='group', y='value', data=data, color='darkblue', alpha=0.5, jitter=True)

plt.title('Boxplot with Individual Points - how2matplotlib.com')
plt.show()

Output:

Matplotlib 分组箱线图:全面掌握数据可视化技巧

在这个例子中,我们首先使用 sns.boxplot() 创建了一个基本的箱线图,然后使用 sns.stripplot() 在箱线图上叠加了散点图。jitter=True 参数用于在水平方向上添加随机抖动,以避免点的重叠。

14. 分面箱线图

当我们需要根据多个分类变量来比较数据分布时,分面箱线图可能会很有用。以下是一个创建分面箱线图的示例:

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np

# 生成示例数据
np.random.seed(42)
n = 200
data = pd.DataFrame({
    'group': np.repeat(['A', 'B'], n),
    'subgroup': np.tile(np.repeat(['X', 'Y'], n//2), 2),
    'category': np.random.choice(['Cat1', 'Cat2', 'Cat3'], 2*n),
    'value': np.concatenate([np.random.normal(0, 1, n), np.random.normal(2, 1, n)])
})

# 创建分面箱线图
g = sns.FacetGrid(data, col='category', height=4, aspect=.7)
g.map(sns.boxplot, 'group', 'value', 'subgroup', palette='Set3')
g.add_legend(title='Subgroup')
g.fig.suptitle('Faceted Boxplot - how2matplotlib.com', y=1.05)
plt.tight_layout()
plt.show()

Output:

Matplotlib 分组箱线图:全面掌握数据可视化技巧

在这个例子中,我们使用 Seaborn 的 FacetGrid 创建了一个分面图,其中每个分面对应一个类别。然后,我们在每个分面中绘制了一个按组和子组分类的箱线图。

15. 带有误差条的箱线图

有时,我们可能希望在箱线图上显示误差条,例如置信区间或标准误差。以下是一个在箱线图上添加误差条的示例:

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)]

# 计算均值和标准误差
means = [np.mean(d) for d in data]
stderrs = [np.std(d) / np.sqrt(len(d)) for d in data]

# 创建带误差条的箱线图
fig, ax = plt.subplots(figsize=(10, 6))
box_plot = ax.boxplot(data)

# 添加误差条
ax.errorbar(range(1, len(data) + 1), means, yerr=stderrs, fmt='o', color='r', capsize=5)

ax.set_title('Boxplot with Error Bars - how2matplotlib.com')
ax.set_ylabel('Values')
ax.set_xticklabels(['Group A', 'Group B', 'Group C'])

plt.show()

Output:

Matplotlib 分组箱线图:全面掌握数据可视化技巧

在这个例子中,我们首先创建了一个基本的箱线图,然后使用 ax.errorbar() 函数添加了误差条。误差条显示了每组数据的均值和标准误差。

结论

通过本文,我们详细探讨了如何使用 Matplotlib 创建各种类型的分组箱线图,从基本的箱线图到高级的多变量和动态箱线图。我们还介绍了如何自定义箱线图的样式、添加统计注释、结合其他类型的图表等技巧。这些技能将帮助您更有效地分析和展示数据,特别是在比较不同组或类别的数据分布时。

记住,箱线图是一种强大的数据可视化工具,但它并不是唯一的选择。根据您的具体需求和数据特征,您可能还需要考虑其他类型的图表,如小提琴图、散点图或直方图。最重要的是选择能最清晰、最有效地传达您的数据洞察的可视化方法。

通过实践和探索,您将能够熟练运用这些技巧,创建出既美观又富有信息量的数据可视化图表。希望本文能为您的数据分析和可视化工作提供有价值的参考和启发。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程