探索更专业的数据可视化技术,包括等高线图、矢量场图、桑基图、树状图和华夫饼图等高级图表类型。
等高线图是一种二维图表,用于表示三维数据的表面。它通过连接相同数值的点形成等高线,常用于表示地形、气象数据、温度分布等连续变化的场数据。
等高线图在地理信息系统(GIS)、气象学、物理学等领域有广泛应用,可以直观地展示数据的分布和变化趋势。
import numpy as np
import matplotlib.pyplot as plt
# 创建网格数据
delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z = np.exp(-X**2 - Y**2)
# 绘制等高线图
fig, ax = plt.subplots()
CS = ax.contour(X, Y, Z)
ax.clabel(CS, inline=True, fontsize=10)
ax.set_title('等高线图示例')
plt.show()
// 创建等高线图数据
const size = 100;
const x = [];
const y = [];
const z = [];
for (let i = 0; i < size; i++) {
x[i] = [];
y[i] = [];
z[i] = [];
for (let j = 0; j < size; j++) {
const xVal = -3 + j * 6 / size;
const yVal = -2 + i * 4 / size;
x[i][j] = xVal;
y[i][j] = yVal;
z[i][j] = Math.exp(-(xVal * xVal + yVal * yVal));
}
}
// 使用Plotly绘制等高线图
const data = [{
x: x[0],
y: y.map(row => row[0]),
z: z,
type: 'contour',
colorscale: 'Viridis'
}];
const layout = {
title: '等高线图示例',
autosize: true
};
Plotly.newPlot('contour-chart', data, layout);
矢量场流线图用于显示向量场的方向和大小,常见于流体力学、电磁学、气象学等领域的可视化。流线表示向量场的流线,展示粒子在该场中的运动路径。
矢量场流线图可以帮助理解流体的流动模式、电磁场的分布情况,以及各种物理场的特性。
import numpy as np
import matplotlib.pyplot as plt
# 创建网格
Y, X = np.mgrid[-3:3:100j, -3:3:100j]
# 计算向量场
U = -1 - X**2 + Y
V = 1 + X - Y**2
# 绘制流线图
fig, ax = plt.subplots()
ax.streamplot(X, Y, U, V, density=1.5, color='purple', linewidth=1)
ax.set_title('矢量场流线图')
plt.show()
// 创建流线图数据
const size = 30;
const x = [];
const y = [];
const u = [];
const v = [];
for (let i = 0; i < size; i++) {
x[i] = [];
y[i] = [];
u[i] = [];
v[i] = [];
for (let j = 0; j < size; j++) {
const xVal = -3 + j * 6 / size;
const yVal = -3 + i * 6 / size;
x[i][j] = xVal;
y[i][j] = yVal;
u[i][j] = -1 - xVal * xVal + yVal;
v[i][j] = 1 + xVal - yVal * yVal;
}
}
// 使用Plotly绘制流线图
const data = [{
type: 'stream',
x: x,
y: y,
u: u,
v: v,
colorscale: 'Viridis'
}];
const layout = {
title: '矢量场流线图',
autosize: true
};
Plotly.newPlot('streamplot-chart', data, layout);
桑基图是一种特定类型的流程图,用于展示能量、材料或成本在系统中的流动和分布。它使用箭头表示流量,箭头的宽度与流量大小成正比。
桑基图特别适合用于能源分析、成本分配、物流分析等场景,能够直观地展示资源在不同环节之间的流动和转化情况。
import matplotlib.pyplot as plt
from matplotlib.sankey import Sankey
# 消费收入与支出数据
flows = [0.7, 0.3, -0.3, -0.1, -0.3, -0.1, -0.1, -0.1]
# 流的标签列表
labels = ["工资", "副业", "生活", "购物", "深造", "运动", "其他", "买书"]
# 流的方向
orientations = [1, 1, 0, -1, 1, -1, 1, 0]
# 创建桑基图
fig = plt.figure(figsize=(10, 6))
sankey = Sankey()
sankey.add(flows=flows, labels=labels, orientations=orientations)
sankey.finish()
plt.title('个人收支桑基图')
plt.show()
// 桑基图数据
const data = {
type: "sankey",
orientation: "h",
node: {
pad: 15,
thickness: 15,
line: {
color: "black",
width: 0.5
},
label: ["工资", "副业", "总收入", "生活", "购物", "深造", "运动", "其他", "买书", "总支出"]
},
link: {
source: [0, 1, 2, 2, 2, 2, 2, 2],
target: [2, 2, 3, 4, 5, 6, 7, 8],
value: [0.7, 0.3, 0.3, 0.1, 0.3, 0.1, 0.1, 0.1]
}
};
const layout = {
title: "个人收支桑基图",
font: {
size: 10
}
};
Plotly.newPlot('sankey-chart', [data], layout);
树状图是一种分层数据可视化方法,通过嵌套矩形展示层次结构数据。矩形的大小表示数值大小,颜色可用于表示其他变量或类别。
树状图特别适合展示层次结构数据,如文件系统大小、组织结构、市场份额分布等,能够有效地利用空间展示大量数据。
import plotly.graph_objects as go
# 创建树状图数据
fig = go.Figure(go.Treemap(
labels=["公司", "研发部", "市场部", "销售部", "财务部", "人力部",
"前端组", "后端组", "测试组", "推广组", "品牌组",
"国内销售", "海外销售", "会计组", "审计组"],
parents=["", "公司", "公司", "公司", "公司", "公司",
"研发部", "研发部", "研发部", "市场部", "市场部",
"销售部", "销售部", "财务部", "财务部"],
values=[100, 30, 25, 25, 10, 10,
10, 12, 8, 12, 13,
13, 12, 6, 4]
))
fig.update_layout(title_text="公司组织结构树状图")
fig.show()
// 创建树状图数据
const data = {
type: "treemap",
labels: ["公司", "研发部", "市场部", "销售部", "财务部", "人力部",
"前端组", "后端组", "测试组", "推广组", "品牌组",
"国内销售", "海外销售", "会计组", "审计组"],
parents: ["", "公司", "公司", "公司", "公司", "公司",
"研发部", "研发部", "研发部", "市场部", "市场部",
"销售部", "销售部", "财务部", "财务部"],
values: [100, 30, 25, 25, 10, 10,
10, 12, 8, 12, 13,
13, 12, 6, 4],
textinfo: "label+value+percent parent",
branchvalues: "total"
};
const layout = {
title: "公司组织结构树状图",
margin: {l: 0, r: 0, b: 0, t: 30}
};
Plotly.newPlot('treemap-chart', [data], layout);
华夫饼图是一种使用网格矩阵来展示比例数据的可视化方法,通过不同颜色的方块表示不同的类别及其比例。它是一种直观展示百分比的替代方案。
华夫饼图特别适合展示有限的几个类别及其占比,如市场份额、投票结果、完成率等,比传统饼图更易于精确比较比例大小。
import matplotlib.pyplot as plt
import numpy as np
# 数据
categories = ['产品A', '产品B', '产品C', '产品D', '其他']
values = [0.3, 0.25, 0.2, 0.15, 0.1]
colors = ['#FF5252', '#448AFF', '#69F0AE', '#FFD740', '#B388FF']
# 创建华夫饼图
fig, ax = plt.subplots(figsize=(8, 6))
waffle_size = 10
data = np.zeros(waffle_size * waffle_size)
color_map = []
# 填充数据
start_idx = 0
for i, (cat, val) in enumerate(zip(categories, values)):
count = int(val * waffle_size * waffle_size)
data[start_idx:start_idx + count] = i + 1
color_map.extend([colors[i]] * count)
start_idx += count
# 绘制热图
data = data.reshape(waffle_size, waffle_size)
cmap = plt.matplotlib.colors.ListedColormap(['white'] + colors)
im = ax.imshow(data, cmap=cmap)
ax.set_xticks(np.arange(-.5, waffle_size, 1), minor=True)
ax.set_yticks(np.arange(-.5, waffle_size, 1), minor=True)
ax.grid(which='minor', color='white', linestyle='-', linewidth=1)
ax.set_xticks([])
ax.set_yticks([])
# 添加图例
legend_elements = [plt.Rectangle((0,0),1,1, fc=color, edgecolor='none', label=f'{cat}: {val*100:.0f}%')
for cat, val, color in zip(categories, values, colors)]
ax.legend(handles=legend_elements, bbox_to_anchor=(1.05, 1), loc='upper left')
plt.title('市场份额华夫饼图')
plt.tight_layout()
plt.show()
// 华夫饼图数据
const categories = ['产品A', '产品B', '产品C', '产品D', '其他'];
const values = [0.3, 0.25, 0.2, 0.15, 0.1];
const colors = ['#FF5252', '#448AFF', '#69F0AE', '#FFD740', '#B388FF'];
const size = 10;
// 创建热图数据
const data = [];
let startIdx = 0;
for (let i = 0; i < values.length; i++) {
const count = Math.floor(values[i] * size * size);
for (let j = 0; j < count; j++) {
data.push(i + 1);
}
startIdx += count;
}
// 补充剩余数据为0
while (data.length < size * size) {
data.push(0);
}
// 重塑为二维数组
const heatmapData = [];
for (let i = 0; i < size; i++) {
heatmapData[i] = [];
for (let j = 0; j < size; j++) {
heatmapData[i][j] = data[i * size + j];
}
}
// 使用Plotly绘制热图
const plotData = [{
z: heatmapData,
type: 'heatmap',
colorscale: [
[0, 'rgba(255,255,255,1)'],
[1/(categories.length + 1), 'rgba(255,255,255,1)'],
[2/(categories.length + 1), colors[0]],
[3/(categories.length + 1), colors[1]],
[4/(categories.length + 1), colors[2]],
[5/(categories.length + 1), colors[3]],
[1, colors[4]]
],
showscale: false,
xgap: 2,
ygap: 2
}];
const layout = {
title: '市场份额华夫饼图',
xaxis: {showgrid: false, showticklabels: false},
yaxis: {showgrid: false, showticklabels: false},
margin: {l: 50, r: 150, b: 50, t: 50},
height: 450,
annotations: []
};
// 添加图例
for (let i = 0; i < categories.length; i++) {
const percentage = (values[i] * 100).toFixed(0);
layout.annotations.push({
x: 1.05,
y: 1 - (i * 0.1),
xref: 'paper',
yref: 'paper',
text: `■ ${categories[i]}: ${percentage}%`,
showarrow: false,
font: {size: 12}
});
}
Plotly.newPlot('waffle-chart', plotData, layout);
甘特图是一种条形图,用于显示项目进度和任务安排。它以水平条形表示任务,条形的长度表示任务持续时间,位置表示开始和结束时间。
甘特图是项目管理中最常用的工具之一,能够清晰地展示项目的时间线、任务依赖关系和进度情况。
import matplotlib.pyplot as plt
import numpy as np
# 任务数据
tasks = ['项目确定', '问卷设计', '试访', '问卷确定', '实地执行',
'数据录入', '数据分析', '报告提交']
start_days = [0, 1.5, 2.5, 3.5, 3, 5.5, 6, 7.5]
durations = [2, 1, 0.5, 0.5, 3, 1, 1.5, 0.5]
colors = ['#FF5252', '#448AFF', '#69F0AE', '#FFD740', '#B388FF',
'#FF4081', '#00BCD4', '#8BC34A']
# 创建甘特图
fig, ax = plt.subplots(figsize=(12, 6))
for i, (task, start, duration, color) in enumerate(zip(tasks, start_days, durations, colors)):
ax.barh(i, duration, left=start, color=color, alpha=0.8)
ax.text(start + duration/2, i, task, ha='center', va='center', color='white', fontweight='bold')
# 设置图表
ax.set_yticks(range(len(tasks)))
ax.set_yticklabels(tasks)
ax.set_xlabel('天数')
ax.set_title('项目甘特图')
ax.grid(axis='x', linestyle='--', alpha=0.6)
plt.tight_layout()
plt.show()
// 甘特图数据
const tasks = ['项目确定', '问卷设计', '试访', '问卷确定', '实地执行',
'数据录入', '数据分析', '报告提交'];
const startDays = [0, 1.5, 2.5, 3.5, 3, 5.5, 6, 7.5];
const durations = [2, 1, 0.5, 0.5, 3, 1, 1.5, 0.5];
const colors = ['#FF5252', '#448AFF', '#69F0AE', '#FFD740', '#B388FF',
'#FF4081', '#00BCD4', '#8BC34A'];
// 创建甘特图数据
const traces = [];
for (let i = 0; i < tasks.length; i++) {
traces.push({
x: [startDays[i], startDays[i] + durations[i]],
y: [tasks[i], tasks[i]],
mode: 'lines',
line: {
color: colors[i],
width: 20
},
hoverinfo: 'text',
text: `${tasks[i]}: 第${startDays[i]}天开始,持续${durations[i]}天`
});
}
const layout = {
title: '项目甘特图',
xaxis: {
title: '天数',
range: [0, 10]
},
yaxis: {
title: '任务',
autorange: 'reversed'
},
margin: {l: 100, r: 50, b: 50, t: 50},
height: 400
};
Plotly.newPlot('gantt-chart', traces, layout);
漏斗图用于显示数据在一系列阶段的递减过程,常用于展示转化率、销售流程、筛选过程等。每个阶段的宽度表示数量或比例。
漏斗图特别适合分析销售转化率、用户流失率、招聘流程等场景,能够直观地展示每个阶段的转化情况。
import matplotlib.pyplot as plt
import numpy as np
# 漏斗图数据
stages = ['访问商品', '加购物车', '生成订单', '支付订单', '完成交易']
values = [1000, 500, 300, 200, 150]
percentages = [100, 50, 30, 20, 15]
# 计算漏斗图的x坐标
x1 = np.array(values)
x2 = np.array((x1.max() - x1) / 2)
x3 = [i + j for i, j in zip(x1, x2)]
x3 = np.array(x3)
y = -np.sort(-np.arange(len(stages)))
# 创建漏斗图
fig, ax = plt.subplots(figsize=(10, 8))
# 绘制条形图
rects1 = ax.barh(y, x3, height=0.5, tick_label=stages, color='g', alpha=0.5)
# 绘制辅助条形图
rects2 = ax.barh(y, x2, height=0.5, color='w', alpha=1)
# 添加线条
ax.plot(x3, y, 'black', alpha=0.7)
ax.plot(x2, y, 'black', alpha=0.7)
# 添加百分比标签
for i in range(len(values)):
text_x = x2[i] + (x3[i] - x2[i]) / 2 - 30
text_y = y[i]
ax.text(text_x, text_y, f'{percentages[i]:.2f}%', fontsize=12)
# 隐藏轴脊和刻度
ax.set_xticks([])
for direction in ['top', 'left', 'bottom', 'right']:
ax.spines[direction].set_color('none')
ax.yaxis.set_ticks_position('none')
plt.title('购物流程漏斗图')
plt.tight_layout()
plt.show()
// 漏斗图数据
const stages = ['访问商品', '加购物车', '生成订单', '支付订单', '完成交易'];
const values = [1000, 500, 300, 200, 150];
// 计算百分比
const percentages = values.map((val, idx) => {
return idx === 0 ? 100 : Math.round((val / values[0]) * 100);
});
// 创建漏斗图
const maxValue = Math.max(...values);
const x2 = values.map(val => (maxValue - val) / 2);
const x3 = values.map((val, idx) => val + x2[idx]);
// 使用Plotly绘制漏斗图
const data = [{
type: 'funnel',
y: stages,
x: values,
textinfo: 'value+percent initial',
textposition: 'inside',
marker: {
color: ['#4E79A7', '#F28E2C', '#E15759', '#76B7B2', '#59A14F'],
line: {color: 'white', width: 2}
},
connector: {line: {color: 'white', dash: 'dot', width: 3}}
}];
const layout = {
title: '购物流程漏斗图',
margin: {l: 100, r: 50, b: 50, t: 50},
height: 400,
font: {
size: 12
}
};
Plotly.newPlot('funnel-chart', data, layout);
第8章介绍了多种高级可视化图表类型,包括等高线图、矢量场流线图、桑基图、树状图、华夫饼图、甘特图和漏斗图等。这些图表各有特点,适用于不同的数据类型和分析场景:
选择合适的图表类型是数据可视化的关键,需要根据数据特点和分析目标进行选择。通过本章的学习,读者应该能够根据不同的数据场景选择最适合的可视化方法。