华夫图(Waffle Chart),它是一种信息可视化图表,是一种矩阵式分类数据可视化工具通过小方格组成的网格来展示数据。
图形展示
一、图表类型与组成
华夫图是一种矩阵式分类数据可视化工具,核心元素包括:
网格系统:
由等大小方格组成的矩阵(图中7行×5列)
每个方格代表一个数据单元
颜色编码:
不同颜色表示不同类别(图中4种颜色)
颜色填充规则由数据决定
坐标系统:
X轴:临床特征(X1-X5)
Y轴:患者分组(Y1-Y7)
图例:
解释颜色与类别的对应关系(Category 1-4)
二、如何解读华夫图
纵向阅读:
单列:某临床特征下所有患者的类别分布
例如X1列:观察不同颜色在Y轴上的分布
横向阅读:
单行:某患者组所有临床特征的类别构成
例如Y1行:观察颜色在X轴上的变化
整体分析:
同色区域:识别同类别的聚集模式
特殊位置:左上/右下角方格的类别归属
比例估算:
统计同色方格数量 = 该类别的占比
图中Category 1占比≈8/35≈23%
三、核心功能与作用
多维度展示:
同时呈现两个分类维度(患者×临床特征)
增加颜色维度表示类别变量
模式识别:
发现聚类现象(如某特征普遍为特定类别)
识别异常点(如某患者的特殊类别组合)
资源分配可视化:
不同颜色可表示资源类型
方格位置表示资源分配位置
四、适用领域
领域 | 典型应用 |
---|---|
临床医学 | 患者-病症矩阵分析 |
商业分析 | 产品-特性分布展示 |
教育评估 | 学生-能力维度分析 |
工业工程 | 质量控制特征分布 |
市场调研 | 用户群体偏好映射 |
五、优缺点分析
优势:
直观展示分类数据分布
比饼图更精确显示比例
同时呈现绝对数量和相对比例
易于识别聚类和异常模式
视觉吸引力强(适合演示)
局限性:
不适合大数据集(>100个单元)
难以精确比较小比例差异
颜色选择影响解读(色盲问题)
无法显示连续变量变化
需要图例解释增加认知负荷
六、专业使用指南
颜色设计原则:
高对比度配色(相邻色可区分)
重要类别使用突出颜色
遵循色盲友好准则(避免红绿组合)
标注技巧:
添加标题说明核心发现
重要区域用文字标注
图例位置优先右侧
七、适用场景与限制
推荐使用场景:
展示30-100个数据单元
需要突出分布模式而非精确值
强调类别间的相对比例
中等数量类别(4-8类)
两个清晰的分组维度
应避免场景:
大数据集(>200个单元)
需要精确数值比较
类别过多(>10类)
包含连续变量
时间序列数据
总结
华夫图是离散分类数据可视化的有力工具,特别适合展示中等规模数据集的分布模式。其核心价值在于:
通过视觉模式替代数字比较
同步呈现多个维度的类别关联
快速识别关键数据特征
当数据规模和类别数量控制在合理范围内时,华夫图能提供远超传统统计图表的洞察效率。临床医学中的患者特征分析(如图中所示)是其典型应用场景,能直观揭示患者群体在不同临床特征上的类别分布规律。
思政论
本人也是一个数学建模的参赛者,是一个建模手我知道对于新手小白,刚参加数学建模培训不明白数学建模到底是干什么?、想学但不知道从哪开始学?、看一些课程书籍发现全都看不懂?书上写的数学模型或算法,列了复杂公式定义而代码注释很少却不知道该怎么编写?我想告述大家的是数学建模不是数学,参加比赛也不是考试,应试的学习数学建模不是数学,参加比赛更不是考试,应试的学习方法失效了,听课,老师不会考虑新手的感受,自学看书,更像在看天书且网上的资源少之又少,所以我将在油猴上免费分享自己的建模思路和一些实质性的资料,给大家参考,这样一来既是相互学习又可相互进步,希望大家可以给个好评和关注、收藏,你们的支持是我更新下去的动力,因为有点太晚了,希望大家多点赞和评论对于觉得思路好的话我明天将免费更新代码。
对于新手小白我也收集了一些实质性的资料在这个资料桶中有清风和北海两个老师的课程,跟着这两个老师学习,无论是对于大数据的题目还是优化的体型都可以完美的掌握,并且该资料桶中还附有各种数学建模学习的书籍 https://m.tb.cn/h.hh1fUY3?tk=8ETO4Zktwe5
代码详解
MATLAB华夫图(Waffle Chart)代码解析
函数定义与参数检查
function WafflePlot(data, varargin)
- 定义函数
WafflePlot
,主参数data
为矩阵数据,varargin
支持可选参数
if nargin < 1
data = [1 2 3 1 2;
3 4 1 2 3;
2 1 4 3 2;
4 3 2 1 4;
1 2 3 4 1;
2 3 4 1 2;
3 4 1 2 3];
disp('使用示例数据运行...');
end
- 检查输入参数:若无数据输入,创建7×5示例矩阵并提示
默认参数设置
lw = 1; % 默认边框线宽
labels = {}; % 默认类别标签为空
cmap = []; % 默认颜色映射为空
xlabels = {}; % 默认X轴标签为空
ylabels = {}; % 默认Y轴标签为空
- 初始化关键参数默认值
可选参数解析
if ~isempty(varargin)
for i = 1:2:length(varargin)
param = varargin{i};
value = varargin{i+1};
switch lower(param)
case 'lw' % 边框线宽
lw = value;
case 'labels' % 类别标签
labels = value;
case 'colormap' % 颜色映射
cmap = value;
case 'xlabels' % X轴标签
xlabels = value;
case 'ylabels' % Y轴标签
ylabels = value;
otherwise % 未知参数警告
warning('未知参数: %s', param);
end
end
end
- 遍历可选参数:支持
lw
,labels
,colormap
,xlabels
,ylabels
五个参数 - 参数名不区分大小写(
lower()
转换) - 检测到未知参数时发出警告
图形窗口设置
figureUnits = 'centimeters';
figureWidth = 13;
figureHeight = 15;
figureHandle = figure;
set(gcf, 'Units', figureUnits, 'Position', [0 0 figureWidth figureHeight],...
'Color', [1 1 1]);
- 设置图形尺寸为13×15厘米
- 创建白色背景(
[1 1 1]
)的图形窗口
数据处理模块
u1 = unique(data); % 获取数据唯一值
num_categories = length(u1); % 计算类别数量
if isempty(labels) % 生成默认类别标签
labels = arrayfun(@(x)sprintf('Category %d', x), u1, 'UniformOutput', false);
disp('使用默认类别标签...');
end
if length(labels) < num_categories % 标签数量检查
warning('提供的标签数量少于类别数,补充默认标签');
for i = (length(labels)+1):num_categories
labels{i} = sprintf('Cat %d', i);
end
end
if isempty(cmap) % 生成默认颜色映射
if num_categories <= 7
cmap = lines(num_categories); % ≤7类用lines配色
else
cmap = turbo(num_categories); % >7类用turbo配色
end
disp('使用默认颜色映射...');
end
if size(cmap,1) < num_categories % 颜色映射检查
warning('提供的颜色数量少于类别数,补充默认颜色');
if num_categories <= 7
default_cmap = lines(num_categories);
else
default_cmap = turbo(num_categories);
end
cmap = [cmap; default_cmap(size(cmap,1)+1:end, :)];
end
if isempty(xlabels) % 生成默认坐标轴标签
xlabels = arrayfun(@(x)sprintf('X%d', x), 1:size(data,2), 'UniformOutput', false);
end
if isempty(ylabels)
ylabels = arrayfun(@(x)sprintf('Y%d', x), 1:size(data,1), 'UniformOutput', false);
end
华夫图绘制核心
[m, n] = size(data); % 获取数据维度
[x, y] = meshgrid(1:n, 1:m); % 创建坐标网格
h_surf = gobjects(m*n, 1); % 预分配图形对象数组
for i = 1:m % 遍历所有数据点
for j = 1:n
x_vert = [j-0.5, j+0.5, j+0.5, j-0.5]; % 计算方格顶点X坐标
y_vert = [i-0.5, i-0.5, i+0.5, i+0.5]; % 计算方格顶点Y坐标
cat_idx = data(i,j); % 当前数据点值
color_idx = find(u1 == cat_idx, 1); % 查找对应颜色索引
if isempty(color_idx) % 未定义类别处理
color = [0.9 0.9 0.9]; % 使用灰色填充
else
color = cmap(color_idx, :); % 获取对应颜色
end
% 绘制彩色方格(白色边框)
h_surf((i-1)*n+j) = patch(x_vert, y_vert, color,...
'EdgeColor', 'w',...
'LineWidth', lw);
end
end
坐标轴与标签设置
hXLabel = xlabel('Clinical'); % X轴标签
hYLabel = ylabel('Patient'); % Y轴标签
axis tight equal % 等比例紧凑坐标轴
set(gca, 'XAxisLocation', 'bottom',... % X轴在底部
'YAxisLocation', 'left',... % Y轴在左侧
'YDir', 'reverse',... % 反转Y轴(顶部为1)
'XTick', 1:n,... % X刻度位置
'YTick', 1:m,... % Y刻度位置
'XTickLabel', xlabels,... % X刻度标签
'YTickLabel', ylabels,... % Y刻度标签
'FontSize', 9, 'FontName', 'Arial',... % 字体设置
'TickLength', [0 0],... % 移除刻度线
'XColor', [0.3 0.3 0.3],... % 坐标轴颜色
'YColor', [0.3 0.3 0.3],...
'LineWidth', 1);
图例生成
legend_handles = gobjects(num_categories, 1); % 预分配图例句柄
for i = 1:num_categories
% 创建与方格样式一致的图例标记
legend_handles(i) = patch(NaN, NaN, cmap(i, :),...
'EdgeColor', 'w',...
'LineWidth', lw);
end
hLegend = legend(legend_handles, labels(1:num_categories),... % 绑定标签
'FontWeight', 'normal',... % 字体权重
'FontSize', 9,... % 字体大小
'Box', 'off',... % 无边框
'Location', 'eastoutside',... % 右侧外部
'Orientation', 'vertical'); % 垂直排列
hLegend.ItemTokenSize = [15, 15]; % 增大图例标记尺寸
标题与布局优化
title('Waffle Chart', 'FontSize', 12, 'FontWeight', 'bold'); % 添加标题
set([hXLabel, hYLabel], 'FontSize', 11, 'FontName', 'Arial') % 坐标轴标签字体
set(gca, 'Position', [0.1 0.1 0.7 0.8]); % 调整坐标轴位置(为图例留空间)
图像输出
figW = figureWidth;
figH = figureHeight;
set(figureHandle, 'PaperUnits', figureUnits);
set(figureHandle, 'PaperPosition', [0 0 figW figH]); % 设置打印尺寸
fileout = 'WaffleChart';
print(figureHandle, [fileout, '.png'], '-r300', '-dpng'); % 输出300dpi PNG
end % 函数结束
MATLAB华夫图(Waffle Chart)代码解析
函数定义与参数检查
function WafflePlot(data, varargin)
- 定义函数
WafflePlot
,主参数data
为矩阵数据,varargin
支持可选参数
if nargin < 1
data = [1 2 3 1 2;
3 4 1 2 3;
2 1 4 3 2;
4 3 2 1 4;
1 2 3 4 1;
2 3 4 1 2;
3 4 1 2 3];
disp('使用示例数据运行...');
end
- 检查输入参数:若无数据输入,创建7×5示例矩阵并提示
默认参数设置
lw = 1; % 默认边框线宽
labels = {}; % 默认类别标签为空
cmap = []; % 默认颜色映射为空
xlabels = {}; % 默认X轴标签为空
ylabels = {}; % 默认Y轴标签为空
- 初始化关键参数默认值
可选参数解析
if ~isempty(varargin)
for i = 1:2:length(varargin)
param = varargin{i};
value = varargin{i+1};
switch lower(param)
case 'lw' % 边框线宽
lw = value;
case 'labels' % 类别标签
labels = value;
case 'colormap' % 颜色映射
cmap = value;
case 'xlabels' % X轴标签
xlabels = value;
case 'ylabels' % Y轴标签
ylabels = value;
otherwise % 未知参数警告
warning('未知参数: %s', param);
end
end
end
- 遍历可选参数:支持
lw
,labels
,colormap
,xlabels
,ylabels
五个参数 - 参数名不区分大小写(
lower()
转换) - 检测到未知参数时发出警告
图形窗口设置
figureUnits = 'centimeters';
figureWidth = 13;
figureHeight = 15;
figureHandle = figure;
set(gcf, 'Units', figureUnits, 'Position', [0 0 figureWidth figureHeight],...
'Color', [1 1 1]);
- 设置图形尺寸为13×15厘米
- 创建白色背景(
[1 1 1]
)的图形窗口
数据处理模块
u1 = unique(data); % 获取数据唯一值
num_categories = length(u1); % 计算类别数量
if isempty(labels) % 生成默认类别标签
labels = arrayfun(@(x)sprintf('Category %d', x), u1, 'UniformOutput', false);
disp('使用默认类别标签...');
end
if length(labels) < num_categories % 标签数量检查
warning('提供的标签数量少于类别数,补充默认标签');
for i = (length(labels)+1):num_categories
labels{i} = sprintf('Cat %d', i);
end
end
if isempty(cmap) % 生成默认颜色映射
if num_categories <= 7
cmap = lines(num_categories); % ≤7类用lines配色
else
cmap = turbo(num_categories); % >7类用turbo配色
end
disp('使用默认颜色映射...');
end
if size(cmap,1) < num_categories % 颜色映射检查
warning('提供的颜色数量少于类别数,补充默认颜色');
if num_categories <= 7
default_cmap = lines(num_categories);
else
default_cmap = turbo(num_categories);
end
cmap = [cmap; default_cmap(size(cmap,1)+1:end, :)];
end
if isempty(xlabels) % 生成默认坐标轴标签
xlabels = arrayfun(@(x)sprintf('X%d', x), 1:size(data,2), 'UniformOutput', false);
end
if isempty(ylabels)
ylabels = arrayfun(@(x)sprintf('Y%d', x), 1:size(data,1), 'UniformOutput', false);
end
华夫图绘制核心
[m, n] = size(data); % 获取数据维度
[x, y] = meshgrid(1:n, 1:m); % 创建坐标网格
h_surf = gobjects(m*n, 1); % 预分配图形对象数组
for i = 1:m % 遍历所有数据点
for j = 1:n
x_vert = [j-0.5, j+0.5, j+0.5, j-0.5]; % 计算方格顶点X坐标
y_vert = [i-0.5, i-0.5, i+0.5, i+0.5]; % 计算方格顶点Y坐标
cat_idx = data(i,j); % 当前数据点值
color_idx = find(u1 == cat_idx, 1); % 查找对应颜色索引
if isempty(color_idx) % 未定义类别处理
color = [0.9 0.9 0.9]; % 使用灰色填充
else
color = cmap(color_idx, :); % 获取对应颜色
end
% 绘制彩色方格(白色边框)
h_surf((i-1)*n+j) = patch(x_vert, y_vert, color,...
'EdgeColor', 'w',...
'LineWidth', lw);
end
end
坐标轴与标签设置
hXLabel = xlabel('Clinical'); % X轴标签
hYLabel = ylabel('Patient'); % Y轴标签
axis tight equal % 等比例紧凑坐标轴
set(gca, 'XAxisLocation', 'bottom',... % X轴在底部
'YAxisLocation', 'left',... % Y轴在左侧
'YDir', 'reverse',... % 反转Y轴(顶部为1)
'XTick', 1:n,... % X刻度位置
'YTick', 1:m,... % Y刻度位置
'XTickLabel', xlabels,... % X刻度标签
'YTickLabel', ylabels,... % Y刻度标签
'FontSize', 9, 'FontName', 'Arial',... % 字体设置
'TickLength', [0 0],... % 移除刻度线
'XColor', [0.3 0.3 0.3],... % 坐标轴颜色
'YColor', [0.3 0.3 0.3],...
'LineWidth', 1);
图例生成
legend_handles = gobjects(num_categories, 1); % 预分配图例句柄
for i = 1:num_categories
% 创建与方格样式一致的图例标记
legend_handles(i) = patch(NaN, NaN, cmap(i, :),...
'EdgeColor', 'w',...
'LineWidth', lw);
end
hLegend = legend(legend_handles, labels(1:num_categories),... % 绑定标签
'FontWeight', 'normal',... % 字体权重
'FontSize', 9,... % 字体大小
'Box', 'off',... % 无边框
'Location', 'eastoutside',... % 右侧外部
'Orientation', 'vertical'); % 垂直排列
hLegend.ItemTokenSize = [15, 15]; % 增大图例标记尺寸
标题与布局优化
title('Waffle Chart', 'FontSize', 12, 'FontWeight', 'bold'); % 添加标题
set([hXLabel, hYLabel], 'FontSize', 11, 'FontName', 'Arial') % 坐标轴标签字体
set(gca, 'Position', [0.1 0.1 0.7 0.8]); % 调整坐标轴位置(为图例留空间)
图像输出
figW = figureWidth;
figH = figureHeight;
set(figureHandle, 'PaperUnits', figureUnits);
set(figureHandle, 'PaperPosition', [0 0 figW figH]); % 设置打印尺寸
fileout = 'WaffleChart';
print(figureHandle, [fileout, '.png'], '-r300', '-dpng'); % 输出300dpi PNG
end % 函数结束