常用图表选择指南:什么数据用什么图表
今天我们要深入探讨一个每个数据分析师、报告编写者和信息传达者都会遇到的核心问题:如何为不同类型的数据选择合适的图表?选对图表,就像选对语言一样,能让你的数据故事娓娓道来;选错图表,则可能让最精彩的洞察被埋没在混乱的视觉表达中。
在这篇全面指南中,我将带你系统了解各类常用图表的适用场景、优缺点,并通过实际的Python代码示例展示如何创建这些图表。无论你是刚刚入门的数据新手,还是希望提升可视化技能的老手,这篇文章都能为你提供实用的参考。我们将从基础概念讲起,逐步深入到实践应用,确保你能真正掌握"什么数据用什么图表"的艺术。
I. 图表选择的重要性与基本原则
在我们深入具体图表之前,先来谈谈为什么图表选择如此重要。人类是视觉动物,我们大脑处理图像的速度比处理文字快6万倍。合适的图表能够:
- 快速传达复杂信息
- 揭示数据中的模式和趋势
- 支持决策过程
- 增强报告的说服力和影响力
相反,选择不当的图表会导致:
- 误导观众得出错误结论
- 掩盖重要的数据洞察
- 让观众感到困惑和沮丧
图表选择的四个基本原则
选择图表时,应该考虑以下四个关键因素:
考虑因素 | 说明 | 示例问题 |
---|---|---|
数据维度 | 数据包含多少变量? | 我需要比较单个变量还是多个变量? |
数据关系 | 你想展示什么类型的关系? | 是比较、分布、组成还是联系? |
受众背景 | 谁将查看这个图表? | 他们是专业人士还是普通大众? |
传达信息 | 你想传达什么核心信息? | 是突出趋势、显示比例还是比较值? |
为了帮助你更好地理解这些原则,下面是一个图表选择过程的可视化总结:
记住这些原则,我们现在可以深入探讨具体的图表类型及其适用场景了。
II. 比较类图表
当需要比较不同类别之间的数值时,比较类图表是最佳选择。这类图表帮助我们回答诸如"哪个产品销量最好?"或"哪个月份的销售额最高?"等问题。
常用比较图表类型
图表类型 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
条形图 | 比较不同类别的数值 | 易于阅读和理解,尤其适用于多个类别 | 不适合显示连续数据的变化趋势 |
柱状图 | 与条形图类似,但柱子垂直放置 | 适合显示时间序列数据的比较 | 类别过多时可能显得拥挤 |
折线图 | 显示数据随时间的变化趋势 | 能清晰展示趋势和变化模式 | 只适用于连续数据,特别是时间序列 |
雷达图 | 比较多个定量变量 | 能够显示多个变量的相对表现 | 阅读和解释较为复杂,容易误导 |
实例:使用条形图比较产品销量
让我们通过一个实际例子来演示如何创建有效的比较图表。假设我们有一家公司的季度产品销售数据,我们想要比较不同产品的表现。
首先,我们需要导入必要的库并准备数据:
import matplotlib.pyplot as plt
import numpy as np
# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei'] # 使用黑体
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
# 示例数据:四种产品在四个季度的销售额(万元)
products = ['产品A', '产品B', '产品C', '产品D']
quarters = ['第一季度', '第二季度', '第三季度', '第四季度']
sales_data = {
'产品A': [120, 135, 148, 160],
'产品B': [90, 110, 130, 150],
'产品C': [80, 95, 110, 125],
'产品D': [70, 85, 100, 115]
}
# 创建图表
fig, ax = plt.subplots(figsize=(10, 6))
# 设置条形图的位置和宽度
x = np.arange(len(quarters))
width = 0.2 # 条形的宽度
# 为每个产品绘制条形
for i, product in enumerate(products):
offset = width * i
ax.bar(x + offset, sales_data[product], width, label=product)
# 添加标签和标题
ax.set_xlabel('季度')
ax.set_ylabel('销售额(万元)')
ax.set_title('各产品季度销售额比较')
ax.set_xticks(x + width * 1.5)
ax.set_xticklabels(quarters)
ax.legend()
# 显示图表
plt.tight_layout()
plt.show()
代码解释:
- 我们首先导入必要的库 - matplotlib用于绘图,numpy用于数值计算。
- 设置中文字体支持,确保中文标签能正确显示。
- 创建示例数据,包含四种产品在四个季度的销售额。
- 使用
plt.subplots()
创建图形和坐标轴对象。 - 使用
np.arange()
创建x轴的位置数组。 - 通过循环为每个产品绘制条形,使用不同的偏移量使条形并排显示。
- 添加必要的标签、标题和图例。
- 使用
plt.tight_layout()
自动调整布局,然后显示图表。
这个条形图有效地比较了不同产品在各季度的销售表现,我们可以清楚地看到产品A始终领先,而所有产品都呈现增长趋势。
折线图示例:显示销售趋势
当我们需要展示数据随时间的变化趋势时,折线图是更好的选择。下面是创建折线图的代码:
# 创建折线图显示销售趋势
plt.figure(figsize=(10, 6))
for product in products:
plt.plot(quarters, sales_data[product], marker='o', label=product, linewidth=2)
plt.xlabel('季度')
plt.ylabel('销售额(万元)')
plt.title('产品销售额趋势分析')
plt.legend()
plt.grid(True, linestyle='--', alpha=0.7)
plt.tight_layout()
plt.show()
代码解释:
- 创建新的图形对象。
- 对每个产品,使用
plt.plot()
绘制折线,并设置标记点、标签和线宽。 - 添加标签、标题和图例。
- 添加网格线提高可读性。
- 显示图表。
折线图清晰地展示了每个产品的增长趋势,特别适合显示时间序列数据的变化模式。
III. 分布类图表
分布类图表帮助我们了解数据的分布特征,包括中心趋势、离散程度和形状。当你需要回答"数据集中在什么范围?"或"数据中存在哪些异常值?"时,这类图表非常有用。
常用分布图表类型
图表类型 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
直方图 | 显示连续数据的分布情况 | 直观显示数据分布形状 | 箱数选择影响解读,可能隐藏细节 |
箱线图 | 显示数据分布的五数概括(最小值、第一四分位数、中位数、第三四分位数、最大值) | 识别异常值,比较多个分布 | 不显示数据分布形状细节 |
密度图 | 显示连续数据的概率密度分布 | 平滑显示分布形状,适合大数据集 | 可能过度平滑掩盖重要特征 |
小提琴图 | 结合箱线图和密度图的优点 | 提供丰富的分布信息 | 阅读和解释相对复杂 |
实例:使用直方图和箱线图分析客户年龄分布
假设我们有一家电子商务公司的客户年龄数据,我们想要了解客户年龄的分布情况。
# 生成示例年龄数据
np.random.seed(42) # 确保结果可重现
customer_ages = np.concatenate([
np.random.normal(35, 5, 300), # 主要客户群体
np.random.normal(60, 8, 100) # 年长客户群体
])
# 创建子图:左侧直方图,右侧箱线图
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
# 绘制直方图
ax1.hist(customer_ages, bins=20, edgecolor='black', alpha=0.7, color='skyblue')
ax1.set_xlabel('年龄')
ax1.set_ylabel('频数')
ax1.set_title('客户年龄分布直方图')
ax1.grid(True, linestyle='--', alpha=0.7)
# 绘制箱线图
ax2.boxplot(customer_ages)
ax2.set_xlabel('客户年龄')
ax2.set_ylabel('年龄')
ax2.set_title('客户年龄分布箱线图')
ax2.grid(True, linestyle='--', alpha=0.7)
plt.tight_layout()
plt.show()
代码解释:
- 使用
np.random.normal()
生成模拟的客户年龄数据,包含两个不同的正态分布群体。 - 创建包含两个子图的图形对象。
- 在左侧子图绘制直方图,显示年龄分布的详细形状。
- 在右侧子图绘制箱线图,显示年龄分布的五数概括和异常值。
- 为每个子图添加标签、标题和网格线。
- 使用
plt.tight_layout()
自动调整布局,然后显示图表。
直方图显示了客户年龄的双峰分布,表明可能有两个主要客户群体:一个 around 35岁,另一个 around 60岁。箱线图则清晰地显示了中位数、四分位数范围和潜在的异常值。
进阶示例:小提琴图
小提琴图结合了箱线图和密度图的优点,提供更丰富的分布信息:
# 假设我们有三个不同地区的客户年龄数据
ages_region1 = np.random.normal(35, 5, 200)
ages_region2 = np.random.normal(45, 7, 200)
ages_region3 = np.random.normal(30, 6, 200)
# 创建小提琴图
plt.figure(figsize=(10, 6))
violin_parts = plt.violinplot([ages_region1, ages_region2, ages_region3],
showmeans=True, showmedians=True)
# 设置颜色
for pc in violin_parts['bodies']:
pc.set_facecolor('lightblue')
pc.set_alpha(0.7)
# 添加标签和标题
plt.xticks([1, 2, 3], ['地区1', '地区2', '地区3'])
plt.xlabel('地区')
plt.ylabel('年龄')
plt.title('不同地区客户年龄分布小提琴图')
plt.grid(True, linestyle='--', alpha=0.7)
plt.tight_layout()
plt.show()
代码解释:
- 生成三个不同地区的模拟年龄数据。
- 使用
plt.violinplot()
创建小提琴图,显示均值和中位数。 - 设置小提琴的颜色和透明度。
- 添加地区标签、坐标轴标签和标题。
- 添加网格线提高可读性。
小提琴图不仅显示了每个地区年龄分布的五数概括(通过内部的箱线和须线),还通过形状展示了分布的密度,提供比简单箱线图更丰富的信息。
IV. 组成类图表
组成类图表展示整体中各部分的相对比例或贡献。当你需要回答"各部分占总体的百分比是多少?"或"资源的分配情况如何?"时,这类图表非常有用。
常用组成图表类型
图表类型 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
饼图 | 显示各部分占整体的比例 | 直观易懂,适合少量类别(<6个) | 类别过多时难以阅读,难以精确比较相似比例 |
环形图 | 与饼图类似,但中间空白可显示额外信息 | 视觉上更轻量,中间可添加总结信息 | 与饼图有相同的局限性 |
堆叠条形图 | 比较各部分的绝对值和对整体的贡献 | 既能比较总量,也能比较组成 | 部分堆叠难以阅读,特别是底层部分 |
堆叠面积图 | 显示各部分随时间变化的组成 | 展示趋势和组成的双重信息 | 只适合时间序列数据,底层部分变化影响上层解读 |
实例:使用饼图和堆叠条形图展示产品销售组成
假设我们想要分析公司全年销售额的产品组成情况。
# 全年各产品销售额数据
yearly_sales = {
'产品A': 560,
'产品B': 480,
'产品C': 410,
'产品D': 370,
'产品E': 280
}
# 创建子图:左侧饼图,右侧堆叠条形图
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))
# 绘制饼图
colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99', '#c7a5ff']
wedges, texts, autotexts = ax1.pie(yearly_sales.values(),
labels=yearly_sales.keys(),
autopct='%1.1f%%',
colors=colors,
startangle=90)
# 美化饼图
ax1.axis('equal') # 确保饼图是圆形
ax1.set_title('全年销售额产品组成')
# 绘制堆叠条形图(按季度展示)
quarterly_sales_stacked = [
[120, 90, 80, 70, 50], # Q1
[135, 110, 95, 85, 60], # Q2
[148, 130, 110, 100, 80],# Q3
[160, 150, 125, 115, 90] # Q4
]
quarters = ['Q1', 'Q2', 'Q3', 'Q4']
products = list(yearly_sales.keys())
bottom = np.zeros(len(quarters))
for i, product in enumerate(products):
sales = [q[i] for q in quarterly_sales_stacked]
ax2.bar(quarters, sales, label=product, bottom=bottom, color=colors[i])
bottom += sales
ax2.set_ylabel('销售额(万元)')
ax2.set_title('各季度销售额产品组成')
ax2.legend()
plt.tight_layout()
plt.show()
代码解释:
- 创建全年各产品销售额数据。
- 创建包含两个子图的图形对象。
- 在左侧子图绘制饼图,显示各产品占全年销售额的比例。
- 设置饼图的颜色、起始角度和百分比格式。
- 在右侧子图绘制堆叠条形图,显示各季度中各产品的销售额组成。
- 使用
bottom
参数实现堆叠效果,并添加图例。 - 添加标签和标题,然后显示图表。
饼图直观地显示了产品A贡献了最大的销售额比例(22.4%),而堆叠条形图不仅显示了各季度的销售总额增长,还展示了各产品在每个季度的贡献变化。
环形图示例
环形图是饼图的变种,中间空白区域可以用来显示总结信息:
# 创建环形图
fig, ax = plt.subplots(figsize=(8, 8))
# 绘制环形图(通过设置wedgeprops的宽度)
wedges, texts, autotexts = ax.pie(yearly_sales.values(),
labels=yearly_sales.keys(),
autopct='%1.1f%%',
colors=colors,
startangle=90,
wedgeprops=dict(width=0.3)) # 设置环的宽度
# 在中间添加总结文本
total_sales = sum(yearly_sales.values())
ax.text(0, 0, f'总销售额\n{total_sales}万元',
ha='center', va='center', fontsize=12, fontweight='bold')
ax.set_title('全年销售额产品组成(环形图)')
plt.show()
代码解释:
- 创建单个图形对象。
- 使用
wedgeprops=dict(width=0.3)
参数将饼图变为环形图。 - 在图表中心添加文本,显示销售总额。
- 设置标题并显示图表。
环形图保留了饼图的直观性,同时中间区域可以用于显示关键总结信息,使图表信息更丰富。
V. 关系类图表
关系类图表用于展示两个或多个变量之间的关系。当你需要回答"两个变量之间有关联吗?"或"多个变量如何相互影响?"时,这类图表非常有用。
常用关系图表类型
图表类型 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
散点图 | 展示两个连续变量之间的关系 | 直观显示相关性、聚类和异常值 | 过度绘制可能隐藏模式,不适合分类变量 |
气泡图 | 散点图的变种,第三个变量通过点的大小表示 | 可展示三个变量之间的关系 | 大小对比可能不精确,复杂度过高 |
热力图 | 显示两个分类变量之间的关系矩阵 | 高效展示大量数据,识别模式 | 不显示精确值,需要颜色解释 |
相关系数矩阵 | 显示多个变量两两之间的相关系数 | 快速识别强相关变量对 | 只显示线性关系,可能忽略非线性关系 |
实例:使用散点图和热力图分析变量关系
假设我们想要分析电子商务网站上产品价格、评价分数和销量之间的关系。
# 生成示例数据
np.random.seed(42)
n_products = 100
price = np.random.uniform(10, 500, n_products)
rating = np.random.uniform(2.5, 5, n_products)
# 销量与价格负相关,与评价正相关
sales = 1000 - 1.5 * price + 300 * rating + np.random.normal(0, 100, n_products)
# 创建子图:左侧散点图,右侧热力图
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))
# 绘制散点图:价格 vs 销量,点大小表示评价分数
scatter = ax1.scatter(price, sales, c=rating, s=rating*20, alpha=0.6, cmap='viridis')
ax1.set_xlabel('价格(元)')
ax1.set_ylabel('销量')
ax1.set_title('产品价格、销量和评价关系散点图')
cbar = plt.colorbar(scatter, ax=ax1)
cbar.set_label('评价分数')
# 计算相关系数矩阵
data = np.array([price, rating, sales])
corr_matrix = np.corrcoef(data)
# 绘制热力图
im = ax2.imshow(corr_matrix, cmap='coolwarm', vmin=-1, vmax=1)
ax2.set_xticks([0, 1, 2])
ax2.set_yticks([0, 1, 2])
ax2.set_xticklabels(['价格', '评价', '销量'])
ax2.set_yticklabels(['价格', '评价', '销量'])
ax2.set_title('变量相关系数热力图')
# 在热力图上添加数值标注
for i in range(3):
for j in range(3):
text = ax2.text(j, i, f'{corr_matrix[i, j]:.2f}',
ha="center", va="center", color="w", fontweight='bold')
plt.tight_layout()
plt.show()
代码解释:
- 生成模拟数据:产品价格、评价分数和销量,其中销量与价格负相关,与评价正相关。
- 创建包含两个子图的图形对象。
- 在左侧子图绘制散点图,x轴表示价格,y轴表示销量,点颜色和大小表示评价分数。
- 添加颜色条并设置标签。
- 计算价格、评价和销量三个变量的相关系数矩阵。
- 在右侧子图绘制热力图,显示相关系数矩阵。
- 在热力图上添加数值标注,显示具体的相关系数。
- 添加标签和标题,然后显示图表。
散点图清晰地显示了价格和销量之间的负相关关系(价格越高,销量越低),同时颜色和点大小显示了评价分数的影响。热力图则定量地展示了三个变量两两之间的相关系数,确认了价格和销量的强负相关(-0.84),以及评价和销量的强正相关(0.77)。
进阶示例:气泡图
气泡图是散点图的扩展,通过点的大小表示第三个连续变量:
# 创建气泡图展示四个变量之间的关系
plt.figure(figsize=(10, 8))
# 添加第四个变量:广告投入
ad_spend = np.random.uniform(100, 1000, n_products)
# 绘制气泡图
scatter = plt.scatter(price, sales, s=ad_spend/10, c=rating, alpha=0.6, cmap='viridis')
plt.xlabel('价格(元)')
plt.ylabel('销量')
plt.title('产品价格、销量、评价和广告投入关系气泡图')
# 添加颜色条
cbar = plt.colorbar(scatter)
cbar.set_label('评价分数')
# 添加图例表示气泡大小(广告投入)
for area in [500, 1000, 1500]:
plt.scatter([], [], s=area/10, c='gray', alpha=0.5, label=f'广告投入: {area}')
plt.legend(scatterpoints=1, frameon=True, labelspacing=1, title='气泡大小表示', loc='upper right')
plt.grid(True, linestyle='--', alpha=0.7)
plt.tight_layout()
plt.show()
代码解释:
- 添加第四个变量:广告投入。
- 使用
s
参数设置点的大小与广告投入成正比。 - 使用
c
参数设置点的颜色与评价分数相关。 - 添加颜色条表示评价分数。
- 创建自定义图例,展示不同气泡大小对应的广告投入值。
- 添加网格线提高可读性。
气泡图同时展示了四个变量之间的关系:x轴(价格)、y轴(销量)、点大小(广告投入)和点颜色(评价分数),提供了丰富的多维数据洞察。
VI. 高级图表与选择指南
在前面的章节中,我们介绍了四大类基本图表类型。在实际应用中,我们常常需要结合多种图表类型,或者使用更高级的可视化技术来传达复杂的数据故事。
高级图表类型
图表类型 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
组合图表 | 同时显示多种关系或多个量级的数据 | 丰富的信息量,多角度分析 | 可能过于复杂,需要谨慎设计 |
小型多图 | 比较多个分组或条件下的数据模式 | 便于比较,避免过度绘制 | 占用空间较大,需要一致的比例尺 |
树状图 | 显示层次结构数据的比例 | 高效利用空间,显示层次结构 | 难以比较非相邻部分,复杂层次难解读 |
桑基图 | 显示流量或资源转移 | 直观显示流动路径和比例 | 复杂流动可能难以跟踪,设计挑战大 |
图表选择指南总结
为了帮助你快速选择合适的图表类型,下面是一个综合指南表:
你想展示… | 推荐图表类型 | 示例 |
---|---|---|
比较少量类别 | 条形图/柱状图 | 不同产品销量比较 |
比较多个时间点 | 折线图 | 月度销售趋势 |
部分与整体关系 | 饼图/环形图(少量类别) 堆叠条形图(多个类别) |
市场份额分布 |
数据分布形状 | 直方图/密度图 | 客户年龄分布 |
统计分布摘要 | 箱线图/小提琴图 | 地区收入分布比较 |
两个变量关系 | 散点图 | 价格与销量关系 |
三个变量关系 | 气泡图 | 价格、销量、评价关系 |
多个变量相关关系 | 热力图 | 变量相关系数矩阵 |
地理空间数据 | 地图 Choropleth | 地区销售分布 |
实例:创建组合图表和小型多图
让我们通过一个综合示例展示如何创建高级图表:
# 创建组合图表:柱状图+折线图
fig, ax1 = plt.subplots(figsize=(10, 6))
# 柱状图:各月销售额
months = ['1月', '2月', '3月', '4月', '5月', '6月']
sales = [120, 135, 148, 160, 175, 190]
ax1.bar(months, sales, color='skyblue', alpha=0.7, label='月度销售额')
ax1.set_xlabel('月份')
ax1.set_ylabel('销售额(万元)', color='skyblue')
ax1.tick_params(axis='y', labelcolor='skyblue')
# 创建第二个y轴
ax2 = ax1.twinx()
growth_rate = [0, 12.5, 9.6, 8.1, 9.4, 8.6] # 环比增长率
ax2.plot(months, growth_rate, color='coral', marker='o', linewidth=2, label='环比增长率')
ax2.set_ylabel('增长率(%)', color='coral')
ax2.tick_params(axis='y', labelcolor='coral')
# 添加标题和图例
plt.title('上半年销售额与增长率')
fig.tight_layout()
plt.show()
# 创建小型多图:各产品季度销售趋势
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
products = ['产品A', '产品B', '产品C', '产品D']
quarters = ['Q1', 'Q2', 'Q3', 'Q4']
for i, ax in enumerate(axes.flat):
product_data = sales_data[products[i]]
ax.plot(quarters, product_data, marker='o', linewidth=2)
ax.set_title(f'{products[i]}销售趋势')
ax.set_ylabel('销售额(万元)')
ax.grid(True, linestyle='--', alpha=0.7)
# 设置相同的y轴范围便于比较
ax.set_ylim(60, 180)
plt.suptitle('各产品季度销售趋势比较', fontsize=16)
plt.tight_layout()
plt.show()
代码解释:
- 创建组合图表:使用双y轴,左侧y轴显示月度销售额(柱状图),右侧y轴显示环比增长率(折线图)。
- 使用
twinx()
创建第二个y轴,确保两个量级不同的变量可以在同一图表中显示。 - 设置不同的颜色和标签区分两个变量。
- 创建小型多图:2x2网格显示四个产品的季度销售趋势。
- 为每个子图设置相同的y轴范围,便于跨产品比较。
- 使用
suptitle()
添加总标题。
组合图表同时展示了销售额的绝对值和增长率的变化,提供了更全面的业务洞察。小型多图则允许我们同时比较多个产品的销售趋势,避免了在单一图表中过度绘制的问题。
VII. 结论与最佳实践
通过本指南,我们系统探讨了各种常用图表类型的适用场景、优缺点和实现方法。正确选择图表类型是有效数据沟通的关键一步,但同样重要的是遵循数据可视化的最佳实践。
数据可视化最佳实践
- 简洁明了:避免不必要的装饰和复杂效果,专注于清晰传达信息。
- 标签清晰:确保坐标轴、标题和图例清晰易读。
- 颜色明智:使用颜色突出重要信息,避免过多颜色造成混乱,考虑色盲友好配色。
- 比例诚实:保持坐标轴比例适当,避免误导性可视化。
- 受众适配:根据受众背景调整图表复杂度和解释深度。
- 故事讲述:使用图表序列讲述连贯的数据故事,而不是孤立展示图表。
最终建议
记住,没有"一刀切"的最佳图表类型。选择图表时始终考虑:
- 你的数据特点和想要展示的关系
- 你的受众和他们的熟悉程度
- 你想要传达的核心信息
实践是提高数据可视化技能的关键。多尝试不同的图表类型,学习优秀可视化的设计原则,并不断从反馈中改进你的可视化作品。
- 点赞
- 收藏
- 关注作者
评论(0)