MATLAB | 怎樣繪製這樣的環形柱狀圖

請尊重原創勞動成果
轉載請註明本文鏈接
及文章作者:slandarer

Hey, 各位又是好久不見,最近忙到後臺消息都有些來不及看,非常抱歉,今天帶來一個環形柱狀圖繪製的簡易小代碼,繪製效果如下:

下面直接給出完整代碼,替換一下數據即可,代碼都有註釋的:

完整代碼

環形柱狀圖

clc; clear
% author : slandarer

% 生成隨機數據
rng(6)
Data = randi([1,100], [6,5]);

% 數據名稱
% 'Class-1','Class-2',... ...,'Class-6'
Name1 = compose('Class-%d'1:6);
Name2 = compose('Prop-%d'1:5);

% 配色
% 更多配色詳見 Zhaoxu Liu / slandarer (2024). 
% 2000 palettes (https://www.mathworks.com/matlabcentral/fileexchange/126969-2000-palettes), 
% MATLAB Central File Exchange.
CList = [0.8941    0.8706    0.8078
    0.9255    0.7412    0.5843
    0.6078    0.6941    0.7333
    0.4745    0.6745    0.7412
    0.2039    0.3961    0.4588
    0.0431    0.2588    0.1294];
% CList = colorDemo(11)

% 數據展示範圍及刻度
YLim = [];
YTick = [];

% =========================================================================
% 開始繪圖
if isempty(YLim) || isempty(YTick)
    tFig = figure('Visible''off');
    tAx = axes('Parent',tFig);
    tAx.NextPlot = 'add';
    bar(tAx, Data, 'stacked')
    if isempty(YLim), YLim = tAx.YLim; else, tAx.YLim = YLim; end
    if isempty(YTick), YTick = tAx.YTick; end
    close(tFig)
end
% 創建圖窗
fig = figure('Units','normalized''Position',[.2,.1,.5,.8]);
ax = axes('Parent',fig, 'Position',[0,0,1,1]);
ax.NextPlot = 'add';
ax.XColor = 'none';
ax.YColor = 'none';
ax.DataAspectRatio = [1,1,1];
% 繪製座標軸和刻度線
TLim = [pi/2, -pi - pi/6];
t01 = linspace(0180);
N = size(Data, 1);
tT = t01.*diff(TLim) + TLim(1);
tX = cos(tT).*(N + N/2 + 1);
tY = sin(tT).*(N + N/2 + 1);
plot(ax, tX, tY, 'LineWidth',.8'Color','k')
ax.XLim = [-1,1].*(N + N/2 + 2);
ax.YLim = [-1,1].*(N + N/2 + 2);
tT = (YTick - YLim(1))./clc; clear
% author : slandarer

% 生成隨機數據
rng(13)
Data = randi([1,100], [6,1]);

% 數據名稱
% 'Class-1','Class-2',... ...,'Class-6'
Name  = compose('Class-%d'1:6);

% 配色
% 更多配色詳見 Zhaoxu Liu / slandarer (2024). 
% 2000 palettes (https://www.mathworks.com/matlabcentral/fileexchange/126969-2000-palettes), 
% MATLAB Central File Exchange.
CList = [0.8941    0.8706    0.8078
    0.9255    0.7412    0.5843
    0.6078    0.6941    0.7333
    0.4745    0.6745    0.7412
    0.2039    0.3961    0.4588
    0.0431    0.2588    0.1294];
% CList = colorDemo(11)

% 數據展示範圍及刻度
YLim = [0,100];
YTick = [];

% =========================================================================
% 開始繪圖
if isempty(YLim) || isempty(YTick)
    tFig = figure('Visible''off');
    tAx = axes('Parent',tFig);
    tAx.NextPlot = 'add';
    bar(tAx, Data)
    if isempty(YLim), YLim = tAx.YLim; else, tAx.YLim = YLim; end
    if isempty(YTick), YTick = tAx.YTick; end
    close(tFig)
end
% 創建圖窗
fig = figure('Units','normalized''Position',[.2,.1,.5,.8]);
ax = axes('Parent',fig, 'Position',[0,0,1,1]);
ax.NextPlot = 'add';
ax.XColor = 'none';
ax.YColor = 'none';
ax.DataAspectRatio = [1,1,1];
% 繪製座標軸和刻度線
TLim = [pi/2, -pi - pi/6];
t01 = linspace(0180);
N = length(Data);
tT = t01.*diff(TLim) + TLim(1);
tX = cos(tT).*(N + N/2 + 1);
tY = sin(tT).*(N + N/2 + 1);
plot(ax, tX, tY, 'LineWidth',.8'Color','k')
ax.XLim = [-1,1].*(N + N/2 + 2);
ax.YLim = [-1,1].*(N + N/2 + 2);
tT = (YTick - YLim(1))./diff(YLim).*diff(TLim) + TLim(1);
tX = [cos(tT).*(N + N/2 + 1); cos(tT).*(N + N/2 + 1 + N/50); tT.*nan];
tY = [sin(tT).*(N + N/2 + 1); sin(tT).*(N + N/2 + 1 + N/50); tT.*nan];
plot(ax, tX(:), tY(:), 'LineWidth',.8'Color','k')
for i = 1:length(YTick)
    iT = tT(i); iR = iT/pi*180;
    YTickHdl = text(ax, tX(2,i), tY(2,i),...
        num2str(YTick(i)), 'FontName','Times New Roman''FontSize',13'HorizontalAlignment','center');
    if mod(iR, 360) > 180 && mod(iR, 360) < 360
        YTickHdl.Rotation = iR + 90;
        YTickHdl.VerticalAlignment = 'top';
    else
        YTickHdl.Rotation = iR - 90;
        YTickHdl.VerticalAlignment = 'bottom';
    end
end
% 繪製柱狀圖
for i = 1:N
    tR = [(N + N/2 + 1 - i - .4).*ones(180), (N + N/2 + 1 - i + .4).*ones(180)];
    tT = t01.*(Data(i) - YLim(1))./diff(YLim).*diff(TLim) + TLim(1);
    tX = cos([tT, tT(end:-1:1)]).*tR;
    tY = sin([tT, tT(end:-1:1)]).*tR;
    fill(ax, tX, tY, CList(i,:), 'LineWidth',1'EdgeColor','k')
end
% 繪製數據名稱
for i = 1:N
    text(ax, 0, N + N/2 + 1 - i, [Name{i},'  '], 'FontName','Times New Roman',...
        'FontSize',16'HorizontalAlignment','right');
end

堆疊環形柱狀圖

clc; clear
% author : slandarer

% 生成隨機數據
rng(6)
Data = randi([1,100], [6,5]);

% 數據名稱
% 'Class-1','Class-2',... ...,'Class-6'
Name1 = compose('Class-%d'1:6);
Name2 = compose('Prop-%d'1:5);

% 配色
% 更多配色詳見 Zhaoxu Liu / slandarer (2024). 
% 2000 palettes (https://www.mathworks.com/matlabcentral/fileexchange/126969-2000-palettes), 
% MATLAB Central File Exchange.
CList = [0.8941    0.8706    0.8078
    0.9255    0.7412    0.5843
    0.6078    0.6941    0.7333
    0.4745    0.6745    0.7412
    0.2039    0.3961    0.4588
    0.0431    0.2588    0.1294];
% CList = colorDemo(11)

% 數據展示範圍及刻度
YLim = [];
YTick = [];

% =========================================================================
% 開始繪圖
if isempty(YLim) || isempty(YTick)
    tFig = figure('Visible''off');
    tAx = axes('Parent',tFig);
    tAx.NextPlot = 'add';
    bar(tAx, Data, 'stacked')
    if isempty(YLim), YLim = tAx.YLim; else, tAx.YLim = YLim; end
    if isempty(YTick), YTick = tAx.YTick; end
    close(tFig)
end
% 創建圖窗
fig = figure('Units','normalized''Position',[.2,.1,.5,.8]);
ax = axes('Parent',fig, 'Position',[0,0,1,1]);
ax.NextPlot = 'add';
ax.XColor = 'none';
ax.YColor = 'none';
ax.DataAspectRatio = [1,1,1];
% 繪製座標軸和刻度線
TLim = [pi/2, -pi - pi/6];
t01 = linspace(0180);
N = size(Data, 1);
tT = t01.*diff(TLim) + TLim(1);
tX = cos(tT).*(N + N/2 + 1);
tY = sin(tT).*(N + N/2 + 1);
plot(ax, tX, tY, 'LineWidth',.8'Color','k')
ax.XLim = [-1,1].*(N + N/2 + 2);
ax.YLim = [-1,1].*(N + N/2 + 2);
tT = (YTick - YLim(1))./diff(YLim).*diff(TLim) + TLim(1);
tX = [cos(tT).*(N + N/2 + 1); cos(tT).*(N + N/2 + 1 + N/50); tT.*nan];
tY = [sin(tT).*(N + N/2 + 1); sin(tT).*(N + N/2 + 1 + N/50); tT.*nan];
plot(ax, tX(:), tY(:), 'LineWidth',.8'Color','k')
for i = 1:length(YTick)
    iT = tT(i); iR = iT/pi*180;
    YTickHdl = text(ax, tX(2,i), tY(2,i),...
        num2str(YTick(i)), 'FontName','Times New Roman''FontSize',13'HorizontalAlignment','center');
    if mod(iR, 360) > 180 && mod(iR, 360) < 360
        YTickHdl.Rotation = iR + 90;
        YTickHdl.VerticalAlignment = 'top';
    else
        YTickHdl.Rotation = iR - 90;
        YTickHdl.VerticalAlignment = 'bottom';
    end
end

Data = cumsum([zeros(N, 1), Data], 2);
% 繪製柱狀圖
for i = 1:N
    for j = 1:(size(Data, 2) - 1)
        tR = [(N + N/2 + 1 - i - .4).*ones(180), (N + N/2 + 1 - i + .4).*ones(180)];
        tT = (t01.*(Data(ij + 1) - Data(ij)) + Data(ij) - YLim(1))./diff(YLim).*diff(TLim) + TLim(1);
        tX = cos([tT, tT(end:-1:1)]).*tR;
        tY = sin([tT, tT(end:-1:1)]).*tR;
        tHdl = fill(ax, tX, tY, CList(j,:), 'LineWidth',1'EdgeColor','k');
        if i == 1
            lgdHdl(j) = tHdl;
        end
    end
end
% 繪製數據名稱
for i = 1:N
    text(ax, 0, N + N/2 + 1 - i, [Name1{i},'  '], 'FontName','Times New Roman',...
        'FontSize',16'HorizontalAlignment','right');
end
% 繪製圖例
legend(lgdHdl, Name2, 'FontName','Times New Roman',...
    'FontSize',16'Box','off''Location','best',...
    'Position',[.22.93 - .04*(size(Data, 2) - 1), .1.04*(size(Data, 2) - 1)]);

更多配色

更多配色可以前往以下fileexchange或者gitee倉庫獲取:

fileexchange

  • Zhaoxu Liu / slandarer (2024). 2000 palettes (https://www.mathworks.com/matlabcentral/fileexchange/126969-2000-palettes), MATLAB Central File Exchange. Retrieved June 22, 2024.

gitee

  • https://gitee.com/slandarer/slanColor

當然若是懶得去下載,這裏也準備了一系列配色數據,複製使用即可:

function CList = colorDemo(N)
% color demos
C{1} = [
    0.8627    0.7608    0.4784
    0.6902    0.7255    0.7451
    0.3882    0.3765    0.3725
    0.5961    0.3686    0.3608
    0.6824    0.7490    0.6588
    0.9451    0.6078    0.2039
];
C{2} = [
    0.1098    0.2000    0.2000
    0.1333    0.3765    0.3765
    0.3882    0.6118    0.6431
    0.8235    0.6784    0.4863
    0.7451    0.4471    0.2706
    0.2745    0.1294    0.1098 
];
C{3} = [
    0.0314    0.0902    0.2275
    0.0039    0.1843    0.3255
    0.0039    0.4275    0.5137
    0.0078    0.6275    0.6353
    0.6745    0.5882    0.4745
    0.9137    0.8706    0.7059
];
C{4} = [
    0.0235    0.5529    0.6157
    0.3961    0.6588    0.6706
    0.5490    0.7412    0.7373
    0.6784    0.7255    0.6314
    0.7373    0.7608    0.6471
    0.8157    0.6863    0.5176
];
C{5} = [
    0.8627    0.6549    0.3804
    0.7765    0.7569    0.4275
    0.5451    0.6118    0.5804
    0.3843    0.5490    0.6471
    0.3529    0.4235    0.4784
    0.3176    0.3098    0.3608
];
C{6} = [
    0.3490    0.3490    0.3608
    0.4510    0.6196    0.6706
    0.1725    0.2118    0.2235
    0.2118    0.3333    0.3686
    0.9765    0.6196    0.5765
    0.7686    0.2392    0.1922
];
C{7} = [
    0.8588    0.7569    0.5922
    0.2157    0.1765    0.1843
    0.3569    0.4863    0.6549
    0.8588    0.6000    0.2588
    0.5529    0.6824    0.5294
    0.5961    0.3529    0.4431
];
C{8} = [
    0.8353    0.6824    0.3882
    0.4314    0.4235    0.5059
    0.9686    0.9255    0.8471
    0.2471    0.2235    0.2235
    0.5765    0.6784    0.5647
    0.7882    0.7176    0.5765
];
C{9} = [
    0.5176    0.4863    0.6392
    0.8941    0.3529    0.3529
    0.9569    0.6510    0.3686
    0.5020    0.4745    0.1686
    0.9490    0.8353    0.4353
    0.1020    0.0706    0.2157
];
C{10} = [
    0.4314    0.4863    0.7255
    0.4824    0.7373    0.8353
    0.8157    0.8863    0.6863
    0.9608    0.8588    0.6000
    0.9098    0.6118    0.5059
    0.8235    0.5176    0.5529
];
C{11} = [
    0.8353    0.4784    0.4275
    0.9098    0.7176    0.3843
    0.6118    0.8039    0.8745
    0.3216    0.3137    0.3216
    0.9020    0.8078    0.6863
    0.7294    0.5843    0.4392
];
C{12} = [
    0.8510    0.3373    0.3608
    0.9490    0.5412    0.5412
    0.9294    0.6627    0.6706
    0.1059    0.7137    0.6863
    0.0314    0.5451    0.7451
    0.0902    0.1569    0.4118
];
CList = C{N};
end

以上已經是完整代碼,若懶得複製可去以下gitee倉庫獲取完整文件夾:

  • https://gitee.com/slandarer/spdraw