Matplotlib 横向条形图:全面掌握数据可视化利器
参考:matplotlib bar chart horizontal
Matplotlib 是 Python 中最流行的数据可视化库之一,它提供了丰富的图表类型和自定义选项。其中,横向条形图(Horizontal Bar Chart)是一种非常有效的数据展示方式,特别适合于比较不同类别之间的数值大小。本文将深入探讨如何使用 Matplotlib 创建横向条形图,从基础绘制到高级定制,全面提升您的数据可视化技能。
1. 横向条形图的基础绘制
横向条形图与普通条形图的主要区别在于条形的方向。在 Matplotlib 中,我们使用 barh()
函数来创建横向条形图。让我们从一个简单的例子开始:
import matplotlib.pyplot as plt
categories = ['Category A', 'Category B', 'Category C', 'Category D']
values = [4, 7, 1, 9]
plt.figure(figsize=(10, 6))
plt.barh(categories, values)
plt.title('How2matplotlib.com - Basic Horizontal Bar Chart')
plt.xlabel('Values')
plt.ylabel('Categories')
plt.show()
Output:
在这个例子中,我们首先导入 Matplotlib 的 pyplot 模块。然后,我们定义了类别和对应的值。使用 plt.figure()
设置图表大小,plt.barh()
函数绘制横向条形图,其中第一个参数是类别,第二个参数是对应的值。最后,我们设置标题和轴标签,并显示图表。
2. 自定义条形颜色和样式
Matplotlib 允许我们自定义条形的颜色和样式,以增强图表的视觉吸引力:
import matplotlib.pyplot as plt
categories = ['Product A', 'Product B', 'Product C', 'Product D']
sales = [1500, 1200, 1700, 1300]
colors = ['#FF9999', '#66B2FF', '#99FF99', '#FFCC99']
plt.figure(figsize=(12, 6))
bars = plt.barh(categories, sales, color=colors, edgecolor='black', linewidth=1)
plt.title('How2matplotlib.com - Sales by Product (Customized Colors)')
plt.xlabel('Sales ()')
plt.ylabel('Products')
for bar in bars:
width = bar.get_width()
plt.text(width, bar.get_y() + bar.get_height()/2, f'{width}',
ha='left', va='center')
plt.show()
Output:
在这个例子中,我们为每个条形指定了不同的颜色,并添加了黑色边框。我们还在每个条形的末端添加了销售额标签。plt.text()
函数用于在图表上添加文本,我们计算了每个条形的宽度和中心位置来放置标签。
3. 堆叠横向条形图
堆叠条形图可以展示同一类别的多个子类别数据:
import matplotlib.pyplot as plt
import numpy as np
categories = ['Category 1', 'Category 2', 'Category 3', 'Category 4']
men_means = [20, 35, 30, 35]
women_means = [25, 32, 34, 20]
plt.figure(figsize=(10, 6))
plt.barh(categories, men_means, label='Men')
plt.barh(categories, women_means, left=men_means, label='Women')
plt.title('How2matplotlib.com - Stacked Horizontal Bar Chart')
plt.xlabel('Values')
plt.ylabel('Categories')
plt.legend()
plt.show()
Output:
在这个例子中,我们使用两次 plt.barh()
调用来创建堆叠效果。第二次调用时,我们使用 left
参数指定每个条形的起始位置,这样就可以将女性数据堆叠在男性数据之上。
4. 分组横向条形图
分组条形图可以并排展示不同类别的数据:
import matplotlib.pyplot as plt
import numpy as np
categories = ['Group A', 'Group B', 'Group C', 'Group D']
men_means = [20, 35, 30, 35]
women_means = [25, 32, 34, 20]
y = np.arange(len(categories))
height = 0.35
plt.figure(figsize=(10, 6))
plt.barh(y - height/2, men_means, height, label='Men')
plt.barh(y + height/2, women_means, height, label='Women')
plt.yticks(y, categories)
plt.title('How2matplotlib.com - Grouped Horizontal Bar Chart')
plt.xlabel('Values')
plt.ylabel('Groups')
plt.legend()
plt.show()
Output:
在这个例子中,我们使用 NumPy 的 arange()
函数创建一个数组来表示类别的位置。然后,我们通过调整 y 坐标来并排放置男性和女性的条形。height
变量用于控制条形的高度。
5. 添加误差条
误差条可以显示数据的不确定性或变异性:
import matplotlib.pyplot as plt
import numpy as np
categories = ['Category A', 'Category B', 'Category C', 'Category D']
values = [4, 7, 1, 9]
errors = [0.5, 1, 0.2, 1.5]
plt.figure(figsize=(10, 6))
plt.barh(categories, values, xerr=errors, capsize=5)
plt.title('How2matplotlib.com - Horizontal Bar Chart with Error Bars')
plt.xlabel('Values')
plt.ylabel('Categories')
plt.show()
Output:
在这个例子中,我们使用 xerr
参数来添加水平误差条。capsize
参数控制误差条末端横线的长度。
6. 使用渐变色
使用渐变色可以使图表更具视觉吸引力:
import matplotlib.pyplot as plt
import numpy as np
categories = ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5']
values = [12, 5, 18, 8, 15]
plt.figure(figsize=(10, 6))
bars = plt.barh(categories, values)
# 创建渐变色
cm = plt.cm.get_cmap('viridis')
colors = cm(np.linspace(0, 1, len(categories)))
for bar, color in zip(bars, colors):
bar.set_color(color)
plt.title('How2matplotlib.com - Horizontal Bar Chart with Gradient Colors')
plt.xlabel('Values')
plt.ylabel('Items')
plt.show()
Output:
在这个例子中,我们使用 Matplotlib 的颜色映射(colormap)功能来创建渐变色。plt.cm.get_cmap('viridis')
获取 ‘viridis’ 颜色映射,然后我们使用 np.linspace()
创建一个均匀分布的颜色序列。
7. 添加数据标签
在条形上直接显示数值可以提高图表的可读性:
import matplotlib.pyplot as plt
categories = ['Product A', 'Product B', 'Product C', 'Product D']
sales = [1500, 1200, 1700, 1300]
plt.figure(figsize=(12, 6))
bars = plt.barh(categories, sales)
plt.title('How2matplotlib.com - Sales by Product with Labels')
plt.xlabel('Sales ()')
plt.ylabel('Products')
for bar in bars:
width = bar.get_width()
plt.text(width, bar.get_y() + bar.get_height()/2, f'{width}',
ha='left', va='center')
plt.show()
Output:
这个例子展示了如何在每个条形的末端添加销售额标签。我们遍历每个条形对象,获取其宽度和位置,然后使用 plt.text()
函数添加标签。
8. 排序条形图
对条形进行排序可以更好地展示数据的分布:
import matplotlib.pyplot as plt
categories = ['Product A', 'Product B', 'Product C', 'Product D', 'Product E']
sales = [1500, 1200, 1700, 1300, 1600]
# 对数据进行排序
sorted_data = sorted(zip(sales, categories), reverse=True)
sales_sorted, categories_sorted = zip(*sorted_data)
plt.figure(figsize=(12, 6))
plt.barh(categories_sorted, sales_sorted)
plt.title('How2matplotlib.com - Sorted Sales by Product')
plt.xlabel('Sales ($)')
plt.ylabel('Products')
plt.show()
Output:
在这个例子中,我们首先将销售额和产品名称打包在一起,然后按销售额降序排序。排序后,我们再将数据解包,用于绘制条形图。
9. 使用对数刻度
当数据范围很大时,使用对数刻度可以更好地展示数据:
import matplotlib.pyplot as plt
import numpy as np
categories = ['Category A', 'Category B', 'Category C', 'Category D']
values = [100, 1000, 10000, 100000]
plt.figure(figsize=(10, 6))
plt.barh(categories, values)
plt.xscale('log')
plt.title('How2matplotlib.com - Horizontal Bar Chart with Log Scale')
plt.xlabel('Values (log scale)')
plt.ylabel('Categories')
# 添加数值标签
for i, v in enumerate(values):
plt.text(v, i, f' {v}', va='center')
plt.show()
Output:
在这个例子中,我们使用 plt.xscale('log')
将 x 轴设置为对数刻度。这样可以更好地展示跨越多个数量级的数据。
10. 条形图与线图结合
有时,将条形图与线图结合可以同时展示多种类型的数据:
import matplotlib.pyplot as plt
categories = ['Jan', 'Feb', 'Mar', 'Apr', 'May']
sales = [1000, 1200, 1100, 1300, 1500]
profit_margin = [0.1, 0.12, 0.11, 0.13, 0.15]
fig, ax1 = plt.subplots(figsize=(12, 6))
# 绘制条形图
ax1.barh(categories, sales, color='skyblue')
ax1.set_xlabel('Sales ($)')
ax1.set_ylabel('Months')
ax1.set_title('How2matplotlib.com - Sales and Profit Margin')
# 创建第二个y轴
ax2 = ax1.twiny()
# 绘制线图
ax2.plot(profit_margin, categories, color='red', marker='o')
ax2.set_xlabel('Profit Margin')
# 添加图例
ax1.legend(['Sales'], loc='lower right')
ax2.legend(['Profit Margin'], loc='upper right')
plt.tight_layout()
plt.show()
Output:
这个例子展示了如何在同一图表中结合条形图和线图。我们使用 plt.subplots()
创建主坐标轴,然后使用 ax1.twiny()
创建一个共享 y 轴的次坐标轴。条形图表示销售额,线图表示利润率。
11. 使用图像填充条形
为了使图表更加生动,我们可以使用图像来填充条形:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
def getImage(path, zoom=0.1):
return OffsetImage(plt.imread(path), zoom=zoom)
categories = ['Apple', 'Banana', 'Orange', 'Grape']
values = [5, 7, 3, 4]
fig, ax = plt.subplots(figsize=(12, 6))
# 假设我们有对应的图片文件
paths = ['apple.png', 'banana.png', 'orange.png', 'grape.png']
bars = ax.barh(categories, values)
for bar, path in zip(bars, paths):
img = getImage(path)
ab = AnnotationBbox(img, (bar.get_width(), bar.get_y() + bar.get_height()/2),
frameon=False, xycoords='data', boxcoords="offset points")
ax.add_artist(ab)
plt.title('How2matplotlib.com - Fruit Sales with Images')
plt.xlabel('Sales')
plt.ylabel('Fruits')
plt.show()
这个例子展示了如何在每个条形的末端添加相应的水果图像。我们使用 OffsetImage
和 AnnotationBbox
来添加和定位图像。请注意,您需要准备相应的图像文件才能运行这个示例。
12. 条形图动画
创建动画可以展示数据随时间的变化:
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
fig, ax = plt.subplots(figsize=(10, 6))
categories = ['Category A', 'Category B', 'Category C', 'Category D']
values = [0, 0, 0, 0]
bars = ax.barh(categories, values)
ax.set_xlim(0, 100)
ax.set_title('How2matplotlib.com - Animated Horizontal Bar Chart')
ax.set_xlabel('Values')
ax.set_ylabel('Categories')
def animate(frame):
for bar in bars:
bar.set_width(np.random.randint(1, 100))
return bars
anim = animation.FuncAnimation(fig, animate, frames=50, interval=200, blit=True)
plt.show()
Output:
这个例子创建了一个简单的动画,其中条形的长度随机变化。我们使用 matplotlib.animation.FuncAnimation
来创建动画,animate
函数在每一帧更新条形的长度。
13. 多子图横向条形图
当需要比较多组数据时,使用多个子图可以很方便:
import matplotlib.pyplot as plt
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10))
categories1 = ['Product A', 'Product B', 'Product C']
sales1 = [1500, 1200, 1700]
categories2 = ['Service X', 'Service Y', 'Service Z']
sales2 = [2000, 2200, 1800]
ax1.barh(categories1, sales1, color='skyblue')
ax1.set_title('How2matplotlib.com - Product Sales')
ax1.set_xlabel('Sales ()')
ax1.set_ylabel('Products')
ax2.barh(categories2, sales2, color='lightgreen')
ax2.set_title('How2matplotlib.com - Service Revenue')
ax2.set_xlabel('Revenue ()')
ax2.set_ylabel('Services')
plt.tight_layout()
plt.show()
Output:
这个例子创建了两个子图,分别显示产品销售额和服务收入。我们使用 plt.subplots(2, 1)
创建两个垂直排列的子图,然后分别在每个子图上绘制横向条形图。
14. 条形图与散点图结合
结合不同类型的图表可以提供更丰富的信息:
import matplotlib.pyplot as plt
import numpy as np
categories = ['Category A', 'Category B', 'Category C', 'Category D']
values = [4, 7, 1, 9]
scatter_x = [3, 6, 2, 8]
scatter_y = [0.5, 1.5, 2.5, 3.5]
fig, ax1 = plt.subplots(figsize=(12, 6))
ax1.barh(categories, values, alpha=0.7)
ax1.set_xlabel('Bar Values')
ax1.set_ylabel('Categories')
ax1.set_title('How2matplotlib.com - Bar Chart with Scatter Plot')
ax2 = ax1.twiny()
ax2.scatter(scatter_x, scatter_y, color='red', s=100)
ax2.set_xlabel('Scatter Values')
plt.tight_layout()
plt.show()
Output:
这个例子在横向条形图的基础上添加了散点图。我们使用 ax1.twiny()
创建一个共享 y 轴的新 x 轴,然后在这个新坐标系上绘制散点图。
15. 使用极坐标系的横向条形图
虽然不常见,但在某些情况下,使用极坐标系的横向条形图可以提供独特的视角:
import matplotlib.pyplot as plt
import numpy as np
categories = ['Category A', 'Category B', 'Category C', 'Category D', 'Category E']
values = [4, 7, 1, 9, 6]
angles = np.linspace(0, 2*np.pi, len(categories), endpoint=False)
fig, ax = plt.subplots(figsize=(10, 10), subplot_kw=dict(projection='polar'))
bars = ax.bar(angles, values, width=0.5, bottom=0.0, alpha=0.5)
ax.set_xticks(angles)
ax.set_xticklabels(categories)
ax.set_title('How2matplotlib.com - Polar Horizontal Bar Chart')
plt.show()
Output:
这个例子创建了一个极坐标系下的”横向”条形图。我们使用 subplot_kw=dict(projection='polar')
来创建极坐标系,然后使用 ax.bar()
函数绘制条形。这种表示方法可以在圆形布局中比较各个类别的数值。
16. 使用 Seaborn 绘制横向条形图
Seaborn 是基于 Matplotlib 的统计数据可视化库,它提供了更高级的接口来创建美观的图表:
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
# 创建示例数据
data = pd.DataFrame({
'category': ['A', 'B', 'C', 'D', 'E'],
'value': [4, 7, 1, 9, 6]
})
plt.figure(figsize=(10, 6))
sns.set_style("whitegrid")
sns.barplot(x='value', y='category', data=data, palette='viridis')
plt.title('How2matplotlib.com - Seaborn Horizontal Bar Chart')
plt.xlabel('Values')
plt.ylabel('Categories')
plt.show()
Output:
这个例子使用 Seaborn 的 barplot()
函数创建横向条形图。Seaborn 自动处理了数据的排序和颜色映射,使得图表看起来更加专业和美观。
17. 带有误差范围的横向条形图
当数据包含不确定性时,显示误差范围可以提供更全面的信息:
import matplotlib.pyplot as plt
import numpy as np
categories = ['Category A', 'Category B', 'Category C', 'Category D']
means = [4, 7, 1, 9]
std_devs = [0.5, 1, 0.2, 1.5]
fig, ax = plt.subplots(figsize=(10, 6))
y_pos = np.arange(len(categories))
ax.barh(y_pos, means, xerr=std_devs, align='center', alpha=0.7, capsize=5)
ax.set_yticks(y_pos)
ax.set_yticklabels(categories)
ax.invert_yaxis() # labels read top-to-bottom
ax.set_xlabel('Values')
ax.set_title('How2matplotlib.com - Horizontal Bar Chart with Error Bars')
plt.tight_layout()
plt.show()
Output:
这个例子展示了如何添加误差条。xerr
参数用于指定每个条形的误差范围,capsize
参数控制误差条末端横线的长度。
18. 使用颜色映射的横向条形图
颜色映射可以根据数值大小自动为条形分配颜色:
import matplotlib.pyplot as plt
import numpy as np
categories = ['Category A', 'Category B', 'Category C', 'Category D', 'Category E']
values = [4, 7, 1, 9, 6]
fig, ax = plt.subplots(figsize=(10, 6))
cmap = plt.cm.get_cmap('viridis')
colors = cmap(np.array(values) / max(values))
bars = ax.barh(categories, values, color=colors)
sm = plt.cm.ScalarMappable(cmap=cmap, norm=plt.Normalize(vmin=min(values), vmax=max(values)))
sm.set_array([])
cbar = plt.colorbar(sm)
cbar.set_label('Value Intensity')
ax.set_title('How2matplotlib.com - Horizontal Bar Chart with Color Mapping')
ax.set_xlabel('Values')
ax.set_ylabel('Categories')
plt.tight_layout()
plt.show()
这个例子使用 viridis
颜色映射来为条形分配颜色。颜色的深浅根据数值的大小自动调整。我们还添加了一个颜色条来显示颜色与数值的对应关系。
19. 带有标注的横向条形图
在图表中添加标注可以突出显示重要信息:
import matplotlib.pyplot as plt
categories = ['Product A', 'Product B', 'Product C', 'Product D', 'Product E']
sales = [1500, 1200, 1700, 1300, 1600]
fig, ax = plt.subplots(figsize=(12, 6))
bars = ax.barh(categories, sales)
ax.set_title('How2matplotlib.com - Sales by Product with Annotations')
ax.set_xlabel('Sales ()')
ax.set_ylabel('Products')
# 添加数据标签
for i, v in enumerate(sales):
ax.text(v, i, f'{v}', va='center')
# 添加标注
ax.annotate('Best Seller!', xy=(1700, 2), xytext=(1800, 2.5),
arrowprops=dict(facecolor='black', shrink=0.05))
plt.tight_layout()
plt.show()
Output:
这个例子不仅在每个条形末端添加了销售额标签,还使用 ax.annotate()
函数为最佳销售产品添加了一个特殊标注。
20. 分组堆叠横向条形图
当需要同时比较多个类别和子类别时,分组堆叠条形图非常有用:
import matplotlib.pyplot as plt
import numpy as np
categories = ['Category 1', 'Category 2', 'Category 3', 'Category 4']
group1 = [20, 35, 30, 35]
group2 = [25, 32, 34, 20]
group3 = [15, 18, 21, 25]
fig, ax = plt.subplots(figsize=(12, 6))
y = np.arange(len(categories))
height = 0.25
ax.barh(y - height, group1, height, label='Group 1')
ax.barh(y, group2, height, label='Group 2')
ax.barh(y + height, group3, height, label='Group 3')
ax.set_yticks(y)
ax.set_yticklabels(categories)
ax.invert_yaxis()
ax.set_xlabel('Values')
ax.set_title('How2matplotlib.com - Grouped and Stacked Horizontal Bar Chart')
ax.legend()
plt.tight_layout()
plt.show()
Output:
这个例子展示了如何创建分组堆叠的横向条形图。我们为每个组别创建一组条形,并通过调整 y 坐标来并排放置它们。
总结:
本文深入探讨了使用 Matplotlib 创建横向条形图的各种技巧和方法。从基础的绘图开始,我们逐步介绍了如何自定义颜色和样式、创建堆叠和分组条形图、添加误差条和数据标签、使用对数刻度、结合其他图表类型、创建动画效果,以及使用高级库如 Seaborn 等。这些技巧不仅可以帮助您创建更加丰富和信息量大的数据可视化,还能让您的图表更具吸引力和专业性。