電子產(chǎn)業(yè)一站式賦能平臺

PCB聯(lián)盟網(wǎng)

搜索
查看: 86|回復: 0
收起左側

MATLAB|科研繪圖|山脊圖

[復制鏈接]

193

主題

193

帖子

1532

積分

三級會員

Rank: 3Rank: 3

積分
1532
跳轉到指定樓層
樓主
發(fā)表于 2023-11-14 13:09:00 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
點擊上方藍字和“好玩的MATLAB”一起快樂玩耍吧!

好玩的matlab
帶你解鎖不一樣的matlab新玩法

今天介紹一下山脊圖,喜歡此推文的小伙伴們記得點贊+關注+分享!【尊重作者勞動成果,轉載請注明推文鏈接和公眾號名】上周去逛了一下商店看見一個筆架

這突然讓我想起,這個不就像科研繪圖的山脊圖嘛,于是我打算用 MATLAB 復刻一個。


效果圖



山脊圖介紹山脊圖(Ridge Plot),也被稱為Joy Plot,是一種用于可視化數(shù)據(jù)分布的圖表,特別是用于顯示多個組的分布情況。在這種圖表中,每個組的數(shù)據(jù)分布都通過平滑的密度曲線來表示,這些曲線沿著垂直軸堆疊,形成類似山脊的視覺效果。山脊圖是核密度估計(KDE)的一個應用,它提供了比傳統(tǒng)的條形圖或直方圖更平滑的數(shù)據(jù)分布視圖。
用途:山脊圖主要用于展示和比較不同組或類別內(nèi)數(shù)據(jù)的分布情況。它特別適合于以下情境:
比較多個分布:當需要展示和比較多組數(shù)據(jù)的分布形狀時,山脊圖能夠直觀地展示出分布之間的差異。
展現(xiàn)趨勢變化:在時間序列數(shù)據(jù)中,山脊圖可以用來展示數(shù)據(jù)隨時間的變化趨勢。
優(yōu)化空間利用:通過堆疊的方式,山脊圖能在有限的空間內(nèi)展示大量的分布信息。
缺點:
可讀性:對于不熟悉這種圖表的觀眾來說,山脊圖可能難以理解和解讀。
疊加問題:當曲線重疊較多時,可能會導致圖表的某些部分難以區(qū)分。
數(shù)據(jù)量限制:對于數(shù)據(jù)量非常大的數(shù)據(jù)集,山脊圖可能不那么有效,因為過多的曲線會使圖表變得雜亂。
應用場景
時間序列分析:在金融、經(jīng)濟、氣象等領域,用于展示某個變量隨時間的變化趨勢。
社會科學:比如在選舉數(shù)據(jù)分析中,展示不同候選人或黨派在不同地區(qū)或人群中的支持率分布。
生物醫(yī)學:用于展示不同實驗組或治療方法下的生物統(tǒng)計數(shù)據(jù)分布。
繪圖教程線條山脊圖
  • 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')endgrid 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);endyTick = (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');ax = gca;hold off;?

    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); endgrid 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);    endendgrid 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;% 創(chuàng)建一個從紫色到紅色再到黃色的顏色映射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);    endend% 設置軸標簽和標題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; % 顏色數(shù)量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);    endendyTick = (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);    endendyTick = (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;% 創(chuàng)建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);    endendyTick = (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; % 顏色數(shù)量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);    endendyTick = (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');    endendyTick = (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);    endendyTick = (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函數(shù)代碼之前「一張圖搞定繪圖配色問題」有詳細介紹。
    - -THE END- -

    源碼下載:gitee下載:https://gitee.com/iDMatlab/ridgePlot

    QQ 群下載:

    fileexchange 下載:


    參考資料:
    【1】https://it.sohu.com/a/704677145_121123706


    送書活動



    包郵贈送 「北京大學出版社贊助《3D科研繪圖與學術圖表繪制從入門到精通》

    專業(yè)級3D科研繪圖與學術圖表繪制指南:以“設計基本概念+軟件底層原理+案例實際操作”的思路進行全方位講解,涵蓋化學、材料學、生物醫(yī)學等領域的科學可視化的藝術化表達
    實例豐富:我們涵蓋各類繪圖軟件與工具,讓你能夠自如運用不同技術繪制出高質量的圖表。內(nèi)容全面:全流程講解3D科研繪圖與學術圖表繪制的方法,有效填補了現(xiàn)有同類型參考書的空白。經(jīng)驗總結:作者多年一線研發(fā)實戰(zhàn)經(jīng)驗全面歸納整理,毫無保留分享技術要領。大咖力薦:多位大型科技公司技術高管和高校相關領域教研專家推薦。
  • 全彩印刷:圖表案例精彩呈現(xiàn),帶來良好的閱讀體驗,方便理解和學習。
    了解更多
    【抽獎方式及滿足條件】:
    1.關注「好玩的MATLAB 」公眾號和視頻號

    2.給本文點【】+【在看】;
    3.留言區(qū)評論點贊最多的前2名。
    4.本活動只針對從未獲過獎的同學,之前獲過獎的小伙伴,不用參加。
    同時滿足上述4個條件的讀者朋友,包郵贈送一本.
    【開獎時間】:2023年11月15日中午12點
    【領獎方式】:在開獎時加小編私人微信:idmatlab
    掃一掃加管理員微信

  • 回復

    使用道具 舉報

    發(fā)表回復

    您需要登錄后才可以回帖 登錄 | 立即注冊

    本版積分規(guī)則


    聯(lián)系客服 關注微信 下載APP 返回頂部 返回列表