目录



山脊图(Ridge Plot),也被称为Joy Plot,是一种用于可视化数据分布的图表,特别是用于显示多个组的分布情况。在这种图表中,每个组的数据分布都通过平滑的密度曲线来表示,这些曲线沿着垂直轴堆叠,形成类似山脊的视觉效果。山脊图是核密度估计(KDE)的一个应用,它提供了比传统的条形图或直方图更平滑的数据分布视图。
用途:山脊图主要用于展示和比较不同组或类别内数据的分布情况。它特别适合于以下情境:
缺点:
应用场景:
线条山脊图
- data = randn(100,12)+[ 20 22 24 26 28 31 30 28 26 24 22 20];
- lgLable= {'January', 'February', 'March', 'April', 'May', 'June','July', 'August', 'September', 'October', 'November', 'December'};
- colors=makeColorMap([0,0,0;1,1,1],12);
- figure('Position',[476 246 511 620])
- p=0.15;
- yTick=(1:size(data, 2))*p;
- for i = 1:size(data, 2)
- [f, x] = ksdensity(data(:, i));
- f=f+i*p;
- pHandle=plot(x, f, 'LineWidth', 1.5,'color',colors(i,:));
- hold on;
- yline(yTick(i),'-.','LineWidth',1,'Color',pHandle.Color,'HandleVisibility','off')
- end
- grid off;box off;
- legend(lgLable,'box','on','Color',[1,1,1]*0.95,'EdgeColor','none');
- set(gca, 'YTick',yTick , 'YTickLabel',lgLable,'LineWidth', 1.5, 'XMinorTick', 'on', 'TickDir', 'out', ...
- 'fontname','Times new Roman','color',[1,1,1]*0.9);
- xlabel('XXXX-Value');
- ylabel('YYYY-Value');
- title('Ridge Plot');
- hold off;

填充山脊图
-
- data = randn(100,12)+[ 20 22 24 26 28 31 30 28 26 24 22 20];
- lgLable= {'January', 'February', 'March', 'April', 'May', 'June','July', 'August', 'September', 'October', 'November', 'December'};
- % colors=makeColorMap(winter,size(data, 2));
- colors=makeColorMap(jet,size(data, 2));
- figure('Position',[476 246 511 620])
- p =0.2;
- hold on;
- for i = size(data, 2):-1:1
- [f, x] = ksdensity(data(:, i));
- fShifted = f + i * p;
- pHandle = plot(x, fShifted,'color',colors(i,:),'LineWidth', 1.5,'HandleVisibility', 'off');
- yline(i * p, '-.', 'LineWidth', 1, 'Color', colors(i,:),'HandleVisibility', 'off')
- Xfill = [x, fliplr(x)];
- Yfill = [fShifted, ones(1, length(x)) * i * p];
- fill(Xfill, Yfill, pHandle.Color, 'EdgeColor', 'none', 'FaceAlpha', 0.3);
- end
- yTick = (1:size(data, 2)) * p;
- ax = gca;
- hold off;
- set(ax, 'YTick', yTick, ...
- 'YTickLabel', lgLable, ...
- 'LineWidth', 1.5, 'XMinorTick', 'on', 'TickDir', 'out', ...
- 'fontname','Times new Roman');
- xlabel('XXXX-Value');
- ylabel('YYYY-Value');
- title('Ridge Plot');

3D填充山脊图
- data = randn(100,12)+[ 20 22 24 26 28 31 30 28 26 24 22 20];
- lgLabel= {'January', 'February', 'March', 'April', 'May', 'June','July', 'August', 'September', 'October', 'November', 'December'};
- p = 0.2;
- xTick=(1:size(data, 2))*p;
- figure('Position',[476 246 511 620])
- hold on;
- colors=makeColorMap(hsv,size(data, 2));
- legendHandles = zeros(size(data, 2), 1);
- for i = 1:size(data, 2)
- [f, y] = ksdensity(data(:, i));
- xShifted = i * p;
- plot3(xShifted * ones(size(f)), y, f, 'LineWidth', 1.5, 'Color', colors(i,:), 'HandleVisibility', 'off');
- Yfill = [y, fliplr(y)];
- Xfill = [xShifted * ones(1, length(y)), xShifted * ones(1, length(y))];
- Zfill = [f, zeros(size(f))];
- legendHandles(i) = fill3(Xfill, Yfill, Zfill, colors(i,:), 'EdgeColor', 'none', 'FaceAlpha', 0.3);
- end
- grid off;
- box on;
- legend(lgLabel,'box','on','Color',[1,1,1]*0.95,'EdgeColor','none','FontName','Times New Roman','location','best');
- set(gca, 'XTick',xTick, 'XTickLabel',lgLabel,'FontName','Times New Roman','linewidth',1)
- xlabel('XXXX-Value');
- ylabel('YYYY-Value');
- zlabel('ZZZ-Value');
- title('Ridge Plot');
- view([-83.4000 71.6830])
- hold off;

不同核山脊图、添加边际散点密度
- data = randn(100,3)+[ 20 24 28];
- colors=makeColorMap(jet,size(data, 2));
- figure('Position',[476 246 511 620])
- p=0;
- hold on;
- yTick=(1:size(data, 2))*p;
- lineLength = 0.02; % 竖线的长度
- for i = size(data, 2):-1:1
- [f, x] = ksdensity(data(:, i));
- fShifted = f + i * p;
- pHandle = plot(x, fShifted, 'color', colors(i,:), 'LineWidth', 1.5, 'HandleVisibility', 'off');
- yline(i * p, '-.', 'LineWidth', 1, 'Color', colors(i,:), 'HandleVisibility', 'off');
- Xfill = [x, fliplr(x)];
- Yfill = [fShifted, ones(1, length(x)) * i * p];
- fill(Xfill, Yfill, pHandle.Color, 'EdgeColor', 'none', 'FaceAlpha', 0.3);
- for j = 1:length(data(:, i))
- line([data(j, i), data(j, i)], [i * p, i * p + lineLength], 'Color', pHandle.Color, 'LineWidth', 1);
- end
- end
- grid off;box off;
- ax=gca;
- set(ax,'LineWidth', 1.5, 'XMinorTick', 'on', 'TickDir', 'out', ...
- 'fontname','Times new Roman','color',[1,1,1]*0.9);
- ax.YLim=[0,1];
- ax.XLim=[15,32];
- xlabel('XXXX-Value');
- ylabel('YYYY-Value');
- title('Ridge Plot');
- hold off;

横坐标方向、全局渐变的散点图
- data = randn(100,12)+[ 20 22 24 26 28 31 30 28 26 24 22 20];
- lgLabel={'January', 'February', 'March', 'April', 'May', 'June',
- 'July', 'August', 'September', 'October', 'November', 'December'};
- p = 0.2;
- numColors = 256;
- % 创建一个从紫色到红色再到黄色的颜色映射
- colorMap =makeColorMap([0.1490 0.0353 0.5608;0.7305 0.2500 0.4922;0.9569 0.9490 0.1765],numColors);
- % 计算全局的x轴范围
- xMin = min(data, [], 'all');
- xMax = max(data, [], 'all');
- figure('Position',[476 246 511 620])
- hold on;
- for i = size(data, 2):-1:1
- [f(i,:), x] = ksdensity(data(:, i), 'Kernel', 'triangle');
- fShifted = f(i,:) + i * p; % 偏移每个分布
- plot(x, fShifted, 'LineWidth', 1.5, 'color', 'k', 'HandleVisibility', 'off');
- yline(i * p, '-.', 'LineWidth', 1, 'HandleVisibility', 'off');
- for j = 1:length(x)-1
- Xfill = [x(j), x(j+1), x(j+1), x(j)];
- Yfill = [i * p, i * p, fShifted(j+1), fShifted(j)];
- % 计算当前点的颜色比例
- colorRatio = (x(j) - xMin) / (xMax - xMin);
- colorIdx = min(numColors, max(1, round(colorRatio * (numColors - 1)) + 1));
- fill(Xfill, Yfill, colorMap(colorIdx, :), 'EdgeColor', 'none', 'FaceAlpha', 0.9);
- end
- end
- % 设置轴标签和标题
- yTick = (1:size(data, 2)) * p;
- set(gca, 'YTick', yTick, ...
- 'YTickLabel', lgLabel, ...
- 'LineWidth', 1.5, 'XMinorTick', 'on', 'TickDir', 'out', ...
- 'fontname','Times new Roman');
- xlabel('XXXX-Value');
- ylabel('YYYY-Value');
- title('Ridge Plot');
- % 设置颜色条
- colormap(colorMap);
- cBar = colorbar;
- cBar.TickDirection = 'out';
- cBar.LineWidth = 1;
- cBar.TickLength = 0.02;
- cBar.FontName = 'Times new Roman';
- caxis([xMin,xMax]);
- hold off;

横坐标方向、单核渐变图
-
- data = randn(100,12) + [20 22 24 26 28 31 30 28 26 24 22 20];
- lgLabel = {'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'};
- numColors = 256; % 颜色数量
- colors = jet(numColors); % 使用jet颜色映射
- figure('Position',[476 246 511 620])
- p = 0.2;
- hold on;
- for i = size(data, 2):-1:1
- [f, x] = ksdensity(data(:, i));
- fShifted = f + i * p;
- plot(x, fShifted, 'LineWidth', 1.5, 'HandleVisibility', 'off');
- yline(i * p, '-.', 'LineWidth', 1, 'HandleVisibility', 'off');
- colorGradient = linspace(1, numColors, length(x));
- for j = 1:length(x)-1
- Xfill = [x(j), x(j+1), x(j+1), x(j)];
- Yfill = [i * p, i * p, fShifted(j+1), fShifted(j)];
- fill(Xfill, Yfill, colors(round(colorGradient(j)), :), 'EdgeColor', 'none', 'FaceAlpha', 0.7);
- end
- end
- yTick = (1:size(data, 2)) * p;
- set(gca, 'YTick', yTick, 'YTickLabel', lgLabel, ...
- 'LineWidth', 1.5, 'XMinorTick', 'on', 'TickDir', 'out', ...
- 'fontname', 'Times new Roman');
- xlabel('XXXX-Value');
- ylabel('YYYY-Value');
- title('Ridge Plot');
- colormap(colors);
- cBar = colorbar;
- cBar.TickDirection = 'out';
- cBar.LineWidth = 1;
- cBar.TickLength = 0.02;
- cBar.FontName = 'Times new Roman';
- hold off;

每个山脊图设置不同颜色,且添加边际散点图
- data = randn(100,12)+[ 20 22 24 26 28 31 30 28 26 24 22 20];
- lgLable = {'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'};
- figure('Position', [476 246 511 620])
- p = 0.3;
- lineLength = 0.04; % 竖线的长度
- colors=makeColorMap(hsv,size(data, 2));
- hold on;
- for i = size(data, 2):-1:1
- [f, x] = ksdensity(data(:, i));
- fShifted = f + i * p;
- pHandle = plot(x, fShifted, 'color', colors(i,:), 'LineWidth', 1.5, 'HandleVisibility', 'off');
- yline(i * p, '-.', 'LineWidth', 1, 'Color', colors(i,:), 'HandleVisibility', 'off');
- Xfill = [x, fliplr(x)];
- Yfill = [fShifted, ones(1, length(x)) * i * p];
- fill(Xfill, Yfill, pHandle.Color, 'EdgeColor', 'none', 'FaceAlpha', 0.3);
- for j = 1:length(data(:, i))
- line([data(j, i), data(j, i)], [i * p, i * p + lineLength], 'Color', 'k', 'LineWidth', 1);
- end
- end
- yTick = (1:size(data, 2)) * p;
- set(gca, 'YTick', yTick, ...
- 'YTickLabel', lgLable, ...
- 'LineWidth', 1.5, 'XMinorTick', 'on', 'TickDir', 'out', ...
- 'fontname', 'Times new Roman');
- xlabel('XXXX-Value');
- ylabel('YYYY-Value');
- title('Ridge Plot');

每个山脊图设置不同颜色单核横向颜色渐变
- data = randn(100,12)+[ 20 22 24 26 28 31 30 28 26 24 22 20];
- lgLabel = {'January', 'February', 'March', 'April', 'May', 'June', ...
- 'July', 'August', 'September', 'October', 'November', 'December'};
- p = 0.2;
- numColors = 256;
- % 创建12个不同的颜色映射,每个月一个
- colorMaps = cell(1, 12);
- colorList={parula,turbo,hsv,hot,cool,spring,summer,autumn,winter,gray,bone,copper,pink,jet,lines,colorcube,prism,flag};
- for i = 1:12
- colorMaps{i} = makeColorMap(colorList{i}, numColors);
- end
- % 计算全局的x轴范围
- xMin = min(data, [], 'all');
- xMax = max(data, [], 'all');
- figure('Position', [476 246 511 620])
- hold on;
- for i = size(data, 2):-1:1
- [f(i,:), x] = ksdensity(data(:, i), 'Kernel', 'triangle');
- fShifted = f(i,:) + i * p; % 偏移每个分布
- plot(x, fShifted, 'LineWidth', 1.5, 'color', 'k', 'HandleVisibility', 'off');
- yline(i * p, '-.', 'LineWidth', 1, 'HandleVisibility', 'off');
- currentColorMap = colorMaps{i};
- for j = 1:length(x)-1
- Xfill = [x(j), x(j+1), x(j+1), x(j)];
- Yfill = [i * p, i * p, fShifted(j+1), fShifted(j)];
- colorRatio = (x(j) - xMin) / (xMax - xMin);
- colorIdx = min(numColors, max(1, round(colorRatio * (numColors - 1)) + 1));
- fill(Xfill, Yfill, currentColorMap(colorIdx, :), 'EdgeColor', 'none', 'FaceAlpha', 0.9);
- end
- end
- yTick = (1:size(data, 2)) * p;
- set(gca, 'YTick', yTick, ...
- 'YTickLabel', lgLabel, ...
- 'LineWidth', 1.5, 'XMinorTick', 'on', 'TickDir', 'out', ...
- 'fontname', 'Times new Roman');
- xlabel('XXXX-Value');
- ylabel('YYYY-Value');
- title('Ridge Plot');
- hold off;

山脊图的 Y值映射颜色变化
-
- data = randn(100,12) + [20 22 24 26 28 31 30 28 26 24 22 20];
- lgLabel = {'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'};
- numColors = 100; % 颜色数量
- colors =makeColorMap(jet, numColors);
- figure('Position',[476 246 511 620])
- p = 0.2;
- hold on;
- for i = size(data, 2):-1:1
- [f, x] = ksdensity(data(:, i));
- fShifted = f + i * p;
- plot(x, fShifted, 'LineWidth', 1.5, 'HandleVisibility', 'off');
- yline(i * p, '-.', 'LineWidth', 1, 'HandleVisibility', 'off');
- % 计算整个分布的最小和最大纵坐标
- minY = min(fShifted);
- maxY = max(fShifted);
- for j = 1:length(x)-1
- Xfill = [x(j), x(j+1), x(j+1), x(j)];
- Yfill = [i * p, i * p, fShifted(j+1), fShifted(j)];
- avgY = mean(Yfill(3:4));
- colorIdx = round(((avgY - minY) / (maxY - minY)) * (numColors - 1)) + 1;
- fill(Xfill, Yfill, colors(colorIdx, :), 'EdgeColor', 'none', 'FaceAlpha', 0.6);
- end
- end
- yTick = (1:size(data, 2)) * p;
- set(gca, 'YTick', yTick, 'YTickLabel', lgLabel, ...
- 'LineWidth', 1.5, 'XMinorTick', 'on', 'TickDir', 'out', ...
- 'fontname', 'Times new Roman');
- xlabel('XXXX-Value');
- ylabel('YYYY-Value');
- title('Ridge Plot');
- colormap(colors);
- cBar = colorbar;
- cBar.TickDirection = 'out';
- cBar.LineWidth = 1;
- cBar.TickLength = 0.02;
- cBar.FontName = 'Times new Roman';
- hold off;

四分位点
- data = randn(100,12) + [20 22 24 26 28 31 30 28 26 24 22 20];
- lgLabel = {'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'};
- colors = makeColorMap(jet, size(data, 2));
- figure('Position', [476 246 511 620])
- p = 0.2;
- hold on;
- for i = size(data, 2):-1:1
- [f, x] = ksdensity(data(:, i));
- fShifted = f + i * p;
- pHandle = plot(x, fShifted, 'color', colors(i,:), 'LineWidth', 1.5, 'HandleVisibility', 'off');
- yline(i * p, '-.', 'LineWidth', 1, 'Color', colors(i,:), 'HandleVisibility', 'off')
- Xfill = [x, fliplr(x)];
- Yfill = [fShifted, ones(1, length(x)) * i * p];
- fill(Xfill, Yfill, pHandle.Color, 'EdgeColor', 'none', 'FaceAlpha', 0.3);
- % 计算并标记四分位点
- quartiles = quantile(data(:, i), [0.25 0.50 0.75]);
- for q = quartiles
- [~, idx] = min(abs(x-q));
- plot(q, fShifted(idx), 'o', 'MarkerFaceColor', pHandle.Color, 'MarkerEdgeColor', 'k');
- end
- end
- yTick = (1:size(data, 2)) * p;
- set(gca, 'YTick', yTick, ...
- 'YTickLabel', lgLabel, ...
- 'LineWidth', 1.5, 'XMinorTick', 'on', 'TickDir', 'out', ...
- 'fontname', 'Times new Roman');
- xlabel('XXXX-Value');
- ylabel('YYYY-Value');
- title('Ridge Plot');
- hold off;

- data = randn(100,12) + [20 22 24 26 28 31 30 28 26 24 22 20];
- lgLabel = {'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'};
- colors = makeColorMap(jet, size(data, 2));
- figure('Position', [476 246 511 620])
- p = 0.2;
- hold on;
- for i = size(data, 2):-1:1
- [f, x] = ksdensity(data(:, i));
- fShifted = f + i * p;
- pHandle = plot(x, fShifted, 'color', colors(i,:), 'LineWidth', 1.5, 'HandleVisibility', 'off');
- yline(i * p, '-.', 'LineWidth', 1, 'Color', colors(i,:), 'HandleVisibility', 'off');
- Xfill = [x, fliplr(x)];
- Yfill = [fShifted, ones(1, length(x)) * i * p];
- fill(Xfill, Yfill, pHandle.Color, 'EdgeColor', 'none', 'FaceAlpha', 0.3);
- % 计算并标记四分位点,并绘制竖线
- quartiles = quantile(data(:, i), [0.25 0.50 0.75]);
- for q = quartiles
- [~, idx] = min(abs(x-q));
- plot(q, fShifted(idx), 'o', 'MarkerFaceColor', pHandle.Color, 'MarkerEdgeColor', 'k');
- line([q q], [fShifted(idx) i * p], 'Color', pHandle.Color, 'LineStyle', '-.','LineWidth', 1);
- end
- end
- yTick = (1:size(data, 2)) * p;
- set(gca, 'YTick', yTick, ...
- 'YTickLabel', lgLabel, ...
- 'LineWidth', 1.5, 'XMinorTick', 'on', 'TickDir', 'out', ...
- 'fontname', 'Times new Roman');
- xlabel('XXXX-Value');
- ylabel('YYYY-Value');
- title('Ridge Plot');
- hold off;

其中makeColorMap函数代码之前「一张图搞定绘图配色问题」有详细介绍。