Matplotlib中创建堆叠条形图的全面指南
参考:Create a stacked bar plot in Matplotlib
堆叠条形图是数据可视化中一种强大而versatile的图表类型,它能够同时展示多个类别的数据以及这些类别之间的关系。在Python的Matplotlib库中,创建堆叠条形图是一项常见且有用的任务。本文将全面介绍如何使用Matplotlib创建堆叠条形图,包括基础知识、进阶技巧以及常见的自定义选项。
1. 堆叠条形图的基本概念
堆叠条形图是将多个条形图堆叠在一起的图表类型。每个条形代表一个类别,而每个条形内的不同部分则代表该类别的子类别或组成部分。这种图表类型特别适合展示整体与部分的关系,以及随时间变化的趋势。
让我们从一个简单的例子开始:
import matplotlib.pyplot as plt
import numpy as np
categories = ['A', 'B', 'C', 'D']
values1 = [10, 20, 15, 25]
values2 = [5, 10, 12, 8]
fig, ax = plt.subplots(figsize=(8, 6))
ax.bar(categories, values1, label='Group 1')
ax.bar(categories, values2, bottom=values1, label='Group 2')
ax.set_ylabel('Values')
ax.set_title('Simple Stacked Bar Plot - how2matplotlib.com')
ax.legend()
plt.show()
Output:
在这个例子中,我们创建了一个简单的堆叠条形图,展示了两组数据。ax.bar()
函数用于绘制条形,而bottom
参数用于指定第二组数据的起始位置。
2. 数据准备和组织
创建堆叠条形图的第一步是正确地组织你的数据。通常,你需要将数据组织成一个二维数组或DataFrame,其中行代表不同的类别,列代表堆叠的不同部分。
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 创建示例数据
data = {
'Category': ['A', 'B', 'C', 'D'],
'Value1': [10, 20, 15, 25],
'Value2': [5, 10, 12, 8],
'Value3': [8, 7, 6, 9]
}
df = pd.DataFrame(data)
# 绘制堆叠条形图
fig, ax = plt.subplots(figsize=(10, 6))
df.plot(x='Category', y=['Value1', 'Value2', 'Value3'], kind='bar', stacked=True, ax=ax)
ax.set_ylabel('Values')
ax.set_title('Stacked Bar Plot with Pandas - how2matplotlib.com')
plt.legend(title='Groups')
plt.show()
Output:
在这个例子中,我们使用pandas DataFrame来组织数据,并利用DataFrame的plot
方法直接创建堆叠条形图。stacked=True
参数指定了我们想要创建堆叠图而不是分组条形图。
3. 自定义颜色和样式
Matplotlib提供了丰富的选项来自定义堆叠条形图的外观。你可以更改颜色、边框样式、透明度等。
import matplotlib.pyplot as plt
import numpy as np
categories = ['A', 'B', 'C', 'D']
values1 = [10, 20, 15, 25]
values2 = [5, 10, 12, 8]
values3 = [8, 7, 6, 9]
fig, ax = plt.subplots(figsize=(10, 6))
ax.bar(categories, values1, label='Group 1', color='#ff9999', edgecolor='white')
ax.bar(categories, values2, bottom=values1, label='Group 2', color='#66b3ff', edgecolor='white')
ax.bar(categories, values3, bottom=np.array(values1) + np.array(values2), label='Group 3', color='#99ff99', edgecolor='white')
ax.set_ylabel('Values')
ax.set_title('Customized Stacked Bar Plot - how2matplotlib.com')
ax.legend()
plt.show()
Output:
在这个例子中,我们为每个堆叠部分指定了不同的颜色,并设置了白色的边框。你可以根据需要进一步调整颜色和其他视觉元素。
4. 添加数据标签
为了增加图表的可读性,你可能想要在每个条形上添加数值标签。这可以通过遍历每个条形并使用ax.text()
方法来实现。
import matplotlib.pyplot as plt
import numpy as np
categories = ['A', 'B', 'C', 'D']
values1 = [10, 20, 15, 25]
values2 = [5, 10, 12, 8]
fig, ax = plt.subplots(figsize=(10, 6))
bars1 = ax.bar(categories, values1, label='Group 1')
bars2 = ax.bar(categories, values2, bottom=values1, label='Group 2')
ax.set_ylabel('Values')
ax.set_title('Stacked Bar Plot with Labels - how2matplotlib.com')
ax.legend()
# 添加数据标签
def add_labels(bars):
for bar in bars:
height = bar.get_height()
ax.text(bar.get_x() + bar.get_width()/2., bar.get_y() + height/2,
f'{height}', ha='center', va='center')
add_labels(bars1)
add_labels(bars2)
plt.show()
Output:
这个例子展示了如何在每个堆叠部分的中心添加数值标签。add_labels
函数遍历每个条形,并在适当的位置添加文本。
5. 处理负值
有时,你的数据可能包含负值。Matplotlib可以很好地处理这种情况,自动将负值向下堆叠。
import matplotlib.pyplot as plt
import numpy as np
categories = ['A', 'B', 'C', 'D']
values1 = [10, -5, 15, -8]
values2 = [5, 10, -12, 8]
fig, ax = plt.subplots(figsize=(10, 6))
ax.bar(categories, values1, label='Group 1')
ax.bar(categories, values2, bottom=values1, label='Group 2')
ax.set_ylabel('Values')
ax.set_title('Stacked Bar Plot with Negative Values - how2matplotlib.com')
ax.legend()
plt.show()
Output:
在这个例子中,我们包含了一些负值。注意Matplotlib如何自动处理这些负值,将它们向下堆叠。
6. 创建水平堆叠条形图
除了垂直的堆叠条形图,你也可以创建水平的堆叠条形图。这在类别标签较长或类别数量较多时特别有用。
import matplotlib.pyplot as plt
import numpy as np
categories = ['Category A', 'Category B', 'Category C', 'Category D', 'Category E']
values1 = [10, 20, 15, 25, 18]
values2 = [5, 10, 12, 8, 7]
fig, ax = plt.subplots(figsize=(10, 6))
ax.barh(categories, values1, label='Group 1')
ax.barh(categories, values2, left=values1, label='Group 2')
ax.set_xlabel('Values')
ax.set_title('Horizontal Stacked Bar Plot - how2matplotlib.com')
ax.legend()
plt.show()
Output:
这个例子使用ax.barh()
函数创建水平条形图。注意我们使用left
参数而不是bottom
来指定第二组数据的起始位置。
7. 百分比堆叠条形图
有时,你可能想要展示每个类别中不同部分的相对比例,而不是绝对值。这时可以创建百分比堆叠条形图。
import matplotlib.pyplot as plt
import numpy as np
categories = ['A', 'B', 'C', 'D']
values1 = [10, 20, 15, 25]
values2 = [5, 10, 12, 8]
values3 = [8, 7, 6, 9]
totals = [i + j + k for i, j, k in zip(values1, values2, values3)]
percentages1 = [i / j * 100 for i, j in zip(values1, totals)]
percentages2 = [i / j * 100 for i, j in zip(values2, totals)]
percentages3 = [i / j * 100 for i, j in zip(values3, totals)]
fig, ax = plt.subplots(figsize=(10, 6))
ax.bar(categories, percentages1, label='Group 1')
ax.bar(categories, percentages2, bottom=percentages1, label='Group 2')
ax.bar(categories, percentages3, bottom=[i+j for i,j in zip(percentages1, percentages2)], label='Group 3')
ax.set_ylabel('Percentage')
ax.set_title('Percentage Stacked Bar Plot - how2matplotlib.com')
ax.legend()
plt.show()
Output:
在这个例子中,我们首先计算每个类别的总和,然后计算每个部分占总和的百分比。这样就可以创建一个显示相对比例的堆叠条形图。
8. 多组堆叠条形图
如果你有多组需要比较的堆叠数据,可以创建多组堆叠条形图。
import matplotlib.pyplot as plt
import numpy as np
categories = ['A', 'B', 'C']
group1_1 = [10, 20, 15]
group1_2 = [5, 10, 12]
group2_1 = [12, 18, 22]
group2_2 = [8, 7, 9]
x = np.arange(len(categories))
width = 0.35
fig, ax = plt.subplots(figsize=(12, 6))
ax.bar(x - width/2, group1_1, width, label='Group 1-1')
ax.bar(x - width/2, group1_2, width, bottom=group1_1, label='Group 1-2')
ax.bar(x + width/2, group2_1, width, label='Group 2-1')
ax.bar(x + width/2, group2_2, width, bottom=group2_1, label='Group 2-2')
ax.set_ylabel('Values')
ax.set_title('Multiple Stacked Bar Groups - how2matplotlib.com')
ax.set_xticks(x)
ax.set_xticklabels(categories)
ax.legend()
plt.show()
Output:
这个例子展示了如何创建两组并排的堆叠条形图。我们使用width
参数来控制条形的宽度,并通过调整x坐标来并排放置两组条形。
9. 添加误差线
在某些情况下,你可能需要在堆叠条形图上添加误差线来表示数据的不确定性。
import matplotlib.pyplot as plt
import numpy as np
categories = ['A', 'B', 'C', 'D']
values1 = [10, 20, 15, 25]
values2 = [5, 10, 12, 8]
errors1 = [1, 2, 1.5, 2.5]
errors2 = [0.5, 1, 1.2, 0.8]
fig, ax = plt.subplots(figsize=(10, 6))
ax.bar(categories, values1, yerr=errors1, label='Group 1', capsize=5)
ax.bar(categories, values2, bottom=values1, yerr=errors2, label='Group 2', capsize=5)
ax.set_ylabel('Values')
ax.set_title('Stacked Bar Plot with Error Bars - how2matplotlib.com')
ax.legend()
plt.show()
Output:
在这个例子中,我们使用yerr
参数为每个堆叠部分添加了误差线。capsize
参数控制误差线末端横线的长度。
10. 自定义图例
图例是帮助读者理解图表的重要元素。Matplotlib提供了多种方式来自定义图例的外观和位置。
import matplotlib.pyplot as plt
import numpy as np
categories = ['A', 'B', 'C', 'D']
values1 = [10, 20, 15, 25]
values2 = [5, 10, 12, 8]
values3 = [8, 7, 6, 9]
fig, ax = plt.subplots(figsize=(10, 6))
ax.bar(categories, values1, label='Group 1')
ax.bar(categories, values2, bottom=values1, label='Group 2')
ax.bar(categories, values3, bottom=np.array(values1) + np.array(values2), label='Group 3')
ax.set_ylabel('Values')
ax.set_title('Stacked Bar Plot with Custom Legend - how2matplotlib.com')
# 自定义图例
legend = ax.legend(title='Groups', loc='upper right', bbox_to_anchor=(1.25, 1),
fancybox=True, shadow=True)
plt.tight_layout()
plt.show()
Output:
在这个例子中,我们自定义了图例的标题、位置、边框样式等。bbox_to_anchor
参数用于精确控制图例的位置。
11. 添加网格线
网格线可以帮助读者更准确地读取数值。Matplotlib允许你轻松地添加和自定义网格线。
import matplotlib.pyplot as plt
import numpy as np
categories = ['A', 'B', 'C', 'D']
values1 = [10, 20, 15, 25]
values2 = [5, 10, 12, 8]
fig, ax = plt.subplots(figsize=(10, 6))
ax.bar(categories, values1, label='Group 1')
ax.bar(categories, values2, bottom=values1, label='Group 2')
ax.set_ylabel('Values')
ax.set_title('Stacked Bar Plot with Grid Lines - how2matplotlib.com')
ax.legend()
# 添加网格线
ax.grid(axis='y', linestyle='--', alpha=0.7)
plt.show()
Output:
在这个例子中,我们使用ax.grid()
函数添加了水平网格线。axis='y'
参数指定只显示y轴的网格线,linestyle='--'
设置网格线为虚线,alpha=0.7
调整网格线的透明度。
12. 调整坐标轴
有时你可能需要调整坐标轴的范围、刻度或标签,以更好地展示你的数据。
import matplotlib.pyplot as plt
import numpy as np
categories = ['A', 'B', 'C', 'D']
values1 = [10, 20, 15, 25]
values2 = [5, 10, 12, 8]
fig, ax = plt.subplots(figsize=(10, 6))
ax.bar(categories, values1, label='Group 1')
ax.bar(categories, values2, bottom=values1, label='Group 2')
ax.set_ylabel('Values')
ax.set_title('Stacked Bar Plot with Customized Axes - how2matplotlib.com')
ax.legend()
# 调整y轴范围
ax.set_ylim(0, 50)
# 自定义y轴刻度
ax.set_yticks(np.arange(0, 51, 10))
# 旋转x轴标签
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
Output:
这个例子展示了如何设置y轴的范围和刻度,以及如何旋转x轴的标签。plt.tight_layout()
函数用于自动调整子图参数,以给定的填充适应图形区域。
13. 添加文本注释
在某些情况下,你可能想要在图表上添加额外的文本信息来解释某些特定的数据点或趋势。
import matplotlib.pyplot as plt
import numpy as np
categories = ['A', 'B', 'C', 'D']
values1 = [10, 20, 15, 25]
values2 = [5, 10, 12, 8]
fig, ax = plt.subplots(figsize=(10, 6))
ax.bar(categories, values1, label='Group 1')
ax.bar(categories, values2, bottom=values1, label='Group 2')
ax.set_ylabel('Values')
ax.set_title('Stacked Bar Plot with Annotations - how2matplotlib.com')
ax.legend()
# 添加文本注释
ax.annotate('Highest value', xy=('B', 30), xytext=(3, 35),
arrowprops=dict(facecolor='black', shrink=0.05))
plt.show()
Output:
在这个例子中,我们使用ax.annotate()
函数添加了一个带箭头的文本注释,指向最高的堆叠条形。
14. 使用不同的颜色映射
Matplotlib提供了多种颜色映射,可以用来自动为堆叠条形图的不同部分分配颜色。
import matplotlib.pyplot as plt
import numpy as np
categories = ['A', 'B', 'C', 'D']
values1 = [10, 20, 15, 25]
values2 = [5, 10, 12, 8]
values3 = [8, 7, 6, 9]
fig, ax = plt.subplots(figsize=(10, 6))
cmap = plt.get_cmap("viridis")
colors = cmap(np.linspace(0, 1, 3))
ax.bar(categories, values1, color=colors[0], label='Group 1')
ax.bar(categories, values2, bottom=values1, color=colors[1], label='Group 2')
ax.bar(categories, values3, bottom=np.array(values1) + np.array(values2), color=colors[2], label='Group 3')
ax.set_ylabel('Values')
ax.set_title('Stacked Bar Plot with Color Map - how2matplotlib.com')
ax.legend()
plt.show()
Output:
这个例子使用了”viridis”颜色映射来为堆叠条形图的不同部分分配颜色。你可以尝试其他颜色映射,如”plasma”、”inferno”或”magma”等。
15. 创建分组堆叠条形图
有时,你可能需要比较多个类别的堆叠数据。在这种情况下,可以创建分组堆叠条形图。
import matplotlib.pyplot as plt
import numpy as np
categories = ['Category 1', 'Category 2', 'Category 3']
group1 = {'A': [10, 5, 8], 'B': [20, 10, 7], 'C': [15, 12, 6]}
group2 = {'A': [12, 6, 9], 'B': [18, 9, 8], 'C': [22, 11, 7]}
x = np.arange(len(categories))
width = 0.35
fig, ax = plt.subplots(figsize=(12, 6))
for i, (label, values) in enumerate(group1.items()):
ax.bar(x - width/2, values, width/3, bottom=[sum(group1[k][:j]) for j in range(len(values))], label=f'Group 1 - {label}')
for i, (label, values) in enumerate(group2.items()):
ax.bar(x + width/2, values, width/3, bottom=[sum(group2[k][:j]) for j in range(len(values))], label=f'Group 2 - {label}')
ax.set_ylabel('Values')
ax.set_title('Grouped Stacked Bar Plot - how2matplotlib.com')
ax.set_xticks(x)
ax.set_xticklabels(categories)
ax.legend(loc='upper left', bbox_to_anchor=(1, 1))
plt.tight_layout()
plt.show()
这个例子创建了一个分组堆叠条形图,每组包含三个堆叠的部分。我们使用嵌套的循环来绘制每个组的堆叠条形。
16. 添加数据表格
有时,在图表下方添加一个数据表格可以提供更详细的信息。
import matplotlib.pyplot as plt
import numpy as np
categories = ['A', 'B', 'C', 'D']
values1 = [10, 20, 15, 25]
values2 = [5, 10, 12, 8]
fig, (ax, table_ax) = plt.subplots(2, 1, figsize=(10, 8), gridspec_kw={'height_ratios': [3, 1]})
ax.bar(categories, values1, label='Group 1')
ax.bar(categories, values2, bottom=values1, label='Group 2')
ax.set_ylabel('Values')
ax.set_title('Stacked Bar Plot with Data Table - how2matplotlib.com')
ax.legend()
# 创建数据表格
table_data = [categories, values1, values2]
table = table_ax.table(cellText=table_data, rowLabels=['Category', 'Group 1', 'Group 2'], loc='center')
table_ax.axis('off')
plt.tight_layout()
plt.show()
Output:
这个例子在堆叠条形图下方添加了一个数据表格。我们使用plt.subplots()
创建两个子图,一个用于条形图,另一个用于表格。
17. 创建3D堆叠条形图
虽然不太常见,但Matplotlib也支持创建3D堆叠条形图,这可以在某些特定场景下提供独特的视角。
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
x = np.arange(4)
y = np.arange(3)
x, y = np.meshgrid(x, y)
x = x.ravel()
y = y.ravel()
z = np.zeros_like(x)
dx = dy = 0.8
dz = np.array([1, 2, 3, 4] * 3)
colors = plt.cm.viridis(dz / float(max(dz)))
ax.bar3d(x, y, z, dx, dy, dz, color=colors)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('3D Stacked Bar Plot - how2matplotlib.com')
plt.show()
Output:
这个例子创建了一个3D堆叠条形图。我们使用ax.bar3d()
函数来绘制3D条形,并使用颜色映射来为不同高度的条形分配不同的颜色。
结论
堆叠条形图是一种强大的数据可视化工具,可以同时展示多个类别的数据及其组成部分。Matplotlib提供了丰富的功能来创建和自定义堆叠条形图,从简单的垂直堆叠到复杂的分组3D堆叠都能轻松实现。
通过本文介绍的各种技巧和示例,你应该能够根据自己的需求创建出富有表现力的堆叠条形图。记住,好的数据可视化不仅要准确呈现数据,还要让读者能够轻松理解和解释数据。因此,在创建堆叠条形图时,要注意选择适当的颜色、添加清晰的标签和图例,并根据需要调整各种视觉元素。
最后,建议你多多实践,尝试将这些技巧应用到自己的数据集中,并根据具体需求进行调整和优化。随着经验的积累,你将能够创建出更加专业和有说服力的堆叠条形图。