Matlab小提琴图详解,从密度估计到多维度可视化
创作时间:
作者:
@小白创作中心
Matlab小提琴图详解,从密度估计到多维度可视化
引用
CSDN
1.
https://blog.csdn.net/weixin_31268759/article/details/146167415
小提琴图(Violin Plot)是一种结合箱线图与核密度估计(Kernel Density Estimation, KDE)的先进统计图表,1998年由Hintze和Nelson首次提出。它能同时展示数据的分布形态、概率密度及关键统计量(如中位数、四分位数),弥补了传统箱线图在多模态分布和连续密度展示上的不足,尤其适用于大数据分析和复杂分布比较。
一、小提琴图的核心组成与数学原理
1. 基本结构
- 密度曲线:通过核密度估计得到,左右对称的曲线宽度表示数据在对应值处的概率密度,面积总和为1。
- 内部标记:
- 中位数线(50%分位数):垂直线标记数据集的中间值。
- 箱体范围(可选):使用短粗线或矩形表示Q1-Q3(25%-75%分位数)。
- 须线(可选):显示1.5×IQR范围,或直接调整密度曲线尾部以反映数据范围。
2. 核密度估计(KDE)的数学背景
核密度估计(Kernel Density Estimation, KDE)是一种非参数概率密度估计方法,用于估计随机变量的概率密度函数。其基本思想是将每个数据点视为一个小的核函数(如高斯核),然后将这些核函数叠加起来形成一个平滑的概率密度曲线。KDE的公式可以表示为:
$$
\hat{f}h(x) = \frac{1}{n}\sum{i=1}^{n}K_h(x-x_i)
$$
其中,$K_h$是带宽为$h$的核函数,$x_i$是数据点,$n$是数据点的数量。常见的核函数包括高斯核、Epanechnikov核等。
3. 与箱线图的对比
特性 | 箱线图 | 小提琴图 |
|---|---|---|
分布形态展示 | 仅五数概括,无法显示多峰 | 显示完整密度曲线,包括双峰、偏态 |
数据复杂度 | 适合中小样本量对比 | 适合大样本或高密度区间分析 |
异常值检测 | 明确标记离群点 | 依赖密度尾部辨识,可能不够直观 |
可视化空间需求 | 紧凑,适合多组对比 | 需要更多横向空间以展示密度 |
二、MATLAB实现基础与进阶
1. 基础小提琴图绘制
MATLAB官方未直接提供小提琴图函数,但可通过ksdensity与patch手动创建:
% 调用示例
data1 = randn(1000,1)*0.8 + 2;
data2 = randn(1000,1)*1.5 + 5;
figure; hold on;
plotViolin(data1, 1, [0.2 0.6 0.8]);
plotViolin(data2, 2, [0.8 0.4 0.2]);
xlim([0.5 2.5]);
set(gca, 'XTick', [1 2], 'XTickLabel', {'Group A', 'Group B'});
ylabel('Value');
title('基础小提琴图');
function plotViolin(data, position, color)
% 核密度估计
[f, xi] = ksdensity(data);
f = f / max(f) * 0.4; % 缩放宽度
% 绘制左半部分
patch([position - f, position + fliplr(f)], ...
[xi, fliplr(xi)], color, 'FaceAlpha', 0.6, 'EdgeColor', 'none');
% 添加中位数线
median_val = median(data);
line([position - 0.05, position + 0.05], [median_val, median_val], ...
'Color', 'k', 'LineWidth', 2);
end
2. 增强型小提琴图
(1) 叠加箱线图与散点
% 绘制小提琴图基础
plotViolin(data1, 1, [0.9 0.2 0.2]);
plotViolin(data2, 2, [0.2 0.7 0.3]);
% 在每个小提琴中心添加箱线图
boxplot(data1, 'Positions', 0.9, 'Widths', 0.15, 'Colors', 'k');
boxplot(data2, 'Positions', 2.1, 'Widths', 0.15, 'Colors', 'k');
% 叠加抖动散点
jitter1 = 0.9 + (rand(size(data1)) - 0.5)*0.1;
jitter2 = 2.1 + (rand(size(data2)) - 0.5)*0.1;
scatter(jitter1, data1, 20, [0.9 0.2 0.2], 'filled', 'MarkerEdgeColor', 'k');
scatter(jitter2, data2, 20, [0.2 0.7 0.3], 'filled', 'MarkerEdgeColor', 'k');
(2) 调整带宽与核函数
% 自定义带宽和Epanechnikov核
[f, xi] = ksdensity(data1, 'Bandwidth', 0.5, 'Kernel', 'Epanechnikov');
3. 高级小提琴图实现
% 小提琴图生成程序 - 高级版
clear; clc; close all;
% 生成示例数据(三种不同的分布)
rng(42); % 设置随机种子保证可重复性
data{1} = 1.5*randn(500,1) + 3; % 正态分布N(3, 1.5^2)
data{2} = 0.8*randn(300,1) - 1; % 正态分布N(-1, 0.8^2)
data{3} = 0.6*randn(400,1) + 6; % 正态分布N(6, 0.6^2)
data{4} = 0.4*randn(250,1) + 8; % 正态分布N(8, 0.4^2)
% 参数设置
positions = 1:length(data); % 小提琴位置
bandwidth = []; % 核密度估计带宽(空表示自动选择)
violinWidth = 0.6; % 小提琴最大宽度
colorMap = parula(length(data)); % 颜色映射
medianColor = [1 0.2 0.2]; % 中位数线颜色
meanSymbol = 'd'; % 均值点符号
outlierThresh = 1.5; % 离群值阈值(IQR倍数)
% 初始化图形
figure('Color','white', 'Position', [100, 100, 800, 600])
hold on;
% 为每个数据集绘制小提琴图
for k = 1:length(data)
% 核密度估计
[f, xi] = ksdensity(data{k}, 'Bandwidth', bandwidth);
f = violinWidth * f/max(f); % 归一化到小提琴宽度
% 统计量计算
q = quantile(data{k}, [0.25 0.5 0.75]);
iqr = q(3) - q(1);
lowerWhisker = max(min(data{k}), q(1) - outlierThresh*iqr);
upperWhisker = min(max(data{k}), q(3) + outlierThresh*iqr);
% 绘制小提琴主体
fill([positions(k)-f, fliplr(positions(k)+f)],...
[xi, fliplr(xi)], colorMap(k,:),...
'FaceAlpha', 0.6, 'EdgeColor', 'none',...
'LineWidth', 1.2, 'EdgeAlpha', 0.8);
% 绘制箱线图元素
rectangle('Position', [positions(k)-0.1, q(1), 0.2, q(3)-q(1)],...
'FaceColor', 'w', 'EdgeColor', 'k', 'LineWidth', 1.5);
line([positions(k)-0.1 positions(k)+0.1], [q(2) q(2)],...
'Color', medianColor, 'LineWidth', 2.5); % 中位数线
% 绘制须线
line([positions(k) positions(k)], [lowerWhisker q(1)],...
'Color', 'k', 'LineStyle', '-', 'LineWidth', 1.2);
line([positions(k) positions(k)], [q(3) upperWhisker],...
'Color', 'k', 'LineStyle', '-', 'LineWidth', 1.2);
% 绘制均值标记
meanValue = mean(data{k});
plot(positions(k), meanValue, meanSymbol,...
'MarkerSize', 10, 'MarkerFaceColor', 'w',...
'MarkerEdgeColor', 'k', 'LineWidth', 1.5);
% 标记离群值
outliers = data{k}(data{k} < lowerWhisker | data{k} > upperWhisker);
plot(positions(k)*ones(size(outliers)), outliers, 'ko',...
'MarkerSize', 4, 'LineWidth', 1);
end
% 图形美化
ax = gca;
ax.XTick = positions;
ax.XTickLabel = {'Group A', 'Group B', 'Group C', 'Group D'};
ax.TickLength = [0 0];
ax.FontName = 'Arial';
ax.FontSize = 12;
ax.LineWidth = 1.5;
grid on;
xlim([0.5 length(data)+0.5])
ylabel('Value', 'FontSize',14, 'FontWeight','bold')
title('Advanced Violin Plot with Statistical Markers',...
'FontSize',16, 'FontWeight','bold')
% 添加图例
h = zeros(3,1);
h(1) = plot(NaN,NaN,'-', 'Color', colorMap(1,:), 'LineWidth',5);
h(2) = plot(NaN,NaN,'-', 'Color', medianColor, 'LineWidth',2);
h(3) = plot(NaN,NaN,meanSymbol, 'MarkerFaceColor','w','MarkerEdgeColor','k');
legend(h, {'Distribution', 'Median', 'Mean'},...
'Location','northwest', 'FontSize',12)
% 添加色标
colormap(colorMap)
c = colorbar;
c.Ticks = [];
c.Label.String = 'Group Density Distribution';
c.Label.FontSize = 12;
% 附加说明
annotation('textbox', [0.15 0.82 0.2 0.1],...
'String', {'• Whiskers show 1.5IQR range',...
'• Circles denote outliers'},...
'FitBoxToText','on', 'EdgeColor','none',...
'FontSize',10, 'Color',[0.3 0.3 0.3])
% 调整布局
set(gcf, 'Color','w')
hold off
热门推荐
为什么会出现“毕业即失业”的情况?如何解决“毕业即失业”?
处理Windows电脑卡顿的实用技巧
川西自驾游攻略:探索美景与美食的完美融合
GoFrame框架使用示例与项目结构详解
春节假期,这条旅游路“热辣滚烫”
三明医改向纵深推进:守护人民健康 惠及万家灯火
清华大学“实验室”成果在武清开枝散叶
全面解析20步正确装修流程及注意事项【装修干货】
蛇行走的力学解释和启示
肝病患者,定期复查为何至关重要?
如何优化排班管理的流程以提高效率?
海藻的功效与作用:吃海藻的7个惊人的健康益处
常用铆螺母材料分类
C语言如何计算今天是星期几
对照自查!你的充电宝安全吗?
眼睛长了麦粒肿能挤吗?怎样才能消得快?
47个专业排名第1,清华大学最新专业排名出炉!网友:实力的体现
今年最流行的颜色居然是它?怎么搭都好看!
棕+白,了不得,亲和又高级
如何正确使用滚筒洗衣机,让衣服洗得更干净
灵活就业人员可参保、“试管婴儿”费用可报销……四川推出医保生育支持“政策包”
Go语言Fyne跨平台图形界面框架使用指南
春天的手抄报怎么画:主题创意、绘画技巧与排版设计全攻略
蓝环章鱼:世界上毒性最强的海洋生物之一
“成瘾”的深渊:一场与大脑对抗的竞赛
三亚一游客疑似买到蓝环章鱼:随便买个菜就买到?
吃货的福利:平价美食推荐
张兵已任蓝天集团党委书记、董事长,此前任职烟台交通集团
婚後孕前健康檢查全攻略:項目、費用及補助方案一文掌握
蛇是如何行走的?为何没有脚,蛇依然能“奔跑”?