在数学建模中我们通常需要对数据进行可视化分析,我们经常用到的可视化图形有:柱状图、折线图、散点图。其他的例如矩阵树图、瀑布图、桑基图、箱线图,大家了解的也并不多。在本文,我们将用Python绘制这些图像,并且给出绘制的代码。
-
柱形图
让我们通过一个稍微复杂一点的例子来展示如何使用Python进行数据处理和可视化。假设我们有一组关于一家公司员工的年龄数据,我们想要分析不同年龄段的员工数量,并将这些信息通过柱状图展示出来。
import pandas as pd
import matplotlib.pyplot as plt
# 1. 创建数据
data = {'Name': ['John', 'Anna', 'Peter', 'Linda', 'James', 'Laura', 'David', 'Maria', 'Carl', 'Lisa'],
'Age': [23, 29, 24, 34, 45, 36, 28, 22, 33, 31]}
df = pd.DataFrame(data)
# 2. 数据分型:将年龄分为几个段
# 使用pd.cut进行分段
bins = [20, 25, 30, 35, 40, 50]
labels = ['20-25', '26-30', '31-35', '36-40', '41-50']
df['Age Group'] = pd.cut(df['Age'], bins=bins, labels=labels, right=False)
# 3. 数据分析:计算每个年龄段的人数
age_group_counts = df['Age Group'].value_counts().sort_index()
# 4. 绘制柱状图
plt.figure(figsize=(10, 6))
plt.bar(age_group_counts.index, age_group_counts.values, color='skyblue')
# 添加标题和坐标轴标签
plt.title('Employee Age Distribution')
plt.xlabel('Age Group')
plt.ylabel('Number of Employees')
# 显示图形
plt.show()
-
折线图
这次我们将分析一家公司过去12个月的销售数据。折线图非常适合展示数据随时间变化的趋势。
import pandas as pd
import matplotlib.pyplot as plt
# 1. 创建数据
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
sales = [200, 210, 250, 270, 300, 310, 330, 320, 310, 305, 290, 300]
df = pd.DataFrame({
'Month': months,
'Sales': sales
})
# 2. 绘制折线图
plt.figure(figsize=(10, 6))
plt.plot(df['Month'], df['Sales'], marker='o', linestyle='-', color='b')
# 添加标题和坐标轴标签
plt.title('Monthly Sales Data')
plt.xlabel('Month')
plt.ylabel('Sales')
# 添加网格线
plt.grid(True)
# 显示图形
plt.show()
-
散点图
为了在散点图上加入线性回归线,我们可以使用scipy.stats
库中的linregress
函数来计算回归线的参数,然后使用Matplotlib绘制散点图和回归线。这里,我们将继续使用上一个例子中的数学成绩和阅读成绩的数据。
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# 1. 创建数据
np.random.seed(0) # 设置随机种子以确保结果的可重复性
math_scores = np.random.randint(50, 100, 100) # 生成100名学生的数学成绩
reading_scores = math_scores + np.random.normal(0, 10, 100) # 生成阅读成绩,基于数学成绩稍作调整
df = pd.DataFrame({
'Math Scores': math_scores,
'Reading Scores': reading_scores
})
# 2. 绘制散点图
plt.figure(figsize=(10, 6))
plt.scatter(df['Math Scores'], df['Reading Scores'], color='blue')
# 添加标题和坐标轴标签
plt.title('Math Scores vs Reading Scores')
plt.xlabel('Math Scores')
plt.ylabel('Reading Scores')
# 显示图形
plt.show()
-
矩阵树图
假设我们有一个销售数据集,包含了不同产品的销售额,我们想要通过矩阵树图来展示每个产品的销售额占比。
import matplotlib.pyplot as plt
import squarify # pip install squarify
# 创建数据
labels = ['Product A', 'Product B', 'Product C', 'Product D']
sizes = [500, 300, 200, 100]
# 设置颜色
colors = ['skyblue', 'yellowgreen', 'coral', 'gold']
# 绘制矩阵树图
plt.figure(figsize=(12, 8))
squarify.plot(sizes=sizes, label=labels, color=colors, alpha=0.6)
# 添加标题
plt.title('Sales Volume by Product')
# 删除坐标轴
plt.axis('off')
# 显示图形
plt.show()
-
瀑布图
瀑布图(Waterfall Chart)是一种用于展示数据序列如何从起始值逐步增加或减少到终止值的图形。它特别适合展示财务数据的累计效应,例如公司的收入、成本和最终利润。虽然Python的Matplotlib库没有直接提供绘制瀑布图的函数,但我们可以通过组合使用条形图来实现。
下面是一个简单的瀑布图例子,展示一个公司从初始收入到最终利润的过程,包括各种收入和成本。
import matplotlib.pyplot as plt
# 创建数据
categories = ['Initial Revenue', 'Sales Increase', 'Service Income', 'Product Returns', 'Final Profit']
values = [1000, 300, 120, -50, 1370] # 注意最后一个值是累积总和
# 计算每个条形的起始位置
start = 0
net_values = [start := start + v for v in values[:-1]] # Python 3.8及以上版本的累积求和
net_values.append(values[-1]) # 添加最终利润
# 绘制瀑布图
fig, ax = plt.subplots(figsize=(10, 6))
bars = plt.bar(categories, values, bottom=[0]+net_values[:-1], color=['skyblue', 'skyblue', 'skyblue', 'salmon', 'skyblue'])
# 添加数值标签
for bar in bars:
height = bar.get_height()
ax.annotate(f'{height}',
xy=(bar.get_x() + bar.get_width() / 2, bar.get_y() + height / 2),
xytext=(0, 3), # 3 points vertical offset
textcoords="offset points",
ha='center', va='bottom')
# 设置图表标题和标签
plt.title('Company Profit Waterfall')
plt.xlabel('Category')
plt.ylabel('Value')
# 显示图形
plt.tight_layout()
plt.show()
-
桑基图
桑基图(Sankey Diagram)是一种特殊类型的流图,它通过流的宽度来展示数据量的大小,非常适合表示不同部分之间的转移或流动。在Python中,可以使用matplotlib
库的sankey
模块或plotly
库来绘制桑基图。这里,我们将使用plotly
来创建一个简单的桑基图示例,因为它提供了更直观和交互式的图表。
import plotly.graph_objects as go
# 创建数据
source = [0, 0, 1, 2, 3, 3] # 源节点索引
target = [2, 3, 2, 3, 4, 5] # 目标节点索引
value = [8, 4, 2, 8, 4, 2] # 流量值
# 节点标签
label = ["Source A", "Source B", "Process 1", "Process 2", "Target A", "Target B"]
# 创建桑基图
fig = go.Figure(data=[go.Sankey(
node=dict(
pad=15, # 节点间的间距
thickness=20, # 节点的厚度
line=dict(color="black", width=0.5),
label=label
),
link=dict(
source=source, # 源节点数组
target=target, # 目标节点数组
value=value # 流量值数组
))])
# 添加标题
fig.update_layout(title_text="Basic Sankey Diagram", font_size=10)
# 显示图形
fig.show()
-
箱线图
假设我们有三组学生的数学成绩数据,我们想要通过箱线图来比较这三组学生的成绩分布情况。
import matplotlib.pyplot as plt
import numpy as np
# 准备数据
np.random.seed(10)
data1 = np.random.normal(100, 10, 200)
data2 = np.random.normal(90, 20, 200)
data3 = np.random.normal(80, 30, 200)
data = [data1, data2, data3]
# 绘制箱线图
plt.figure(figsize=(10, 6))
plt.boxplot(data, vert=True, patch_artist=True, labels=['Class 1', 'Class 2', 'Class 3'])
# 添加标题和坐标轴标签
plt.title('Math Scores by Class')
plt.xlabel('Class')
plt.ylabel('Scores')
# 显示图形
plt.show()