这是另一种黑客攻击;在 R2017b 上测试。
您所问的问题之所以难以做到,是因为条形图中的每个组实际上都是一个 Quadrilateral 对象(即多边形)。例如,我们以 1stBar 对象为例:
>> h(1).Face.VertexData
ans =
3×16 single matrix
Columns 1 through 9
0 91.9000 91.9000 0 0 84.9000 84.9000 0 0
0.6545 0.6545 0.8000 0.8000 1.6545 1.6545 1.8000 1.8000 2.6545
0 0 0 0 0 0 0 0 0
Columns 10 through 16
89.4000 89.4000 0 0 72.0000 72.0000 0
2.6545 2.8000 2.8000 3.6545 3.6545 3.8000 3.8000
0 0 0 0 0 0 0
如果我们将这一行添加到代码中:
drawnow; hold on; scatter(h(1).Face.VertexData(1,:), h(1).Face.VertexData(2,:));
我们得到(注意绿色圆圈):
有趣的是VertexData 中的点不是只读的,这意味着我们可以智能地“重新排列”N 条组的VertexData 矩阵以获得所需的结果。这是一种方法(注意我将h重命名为hBar):
% Obtain the old VertexData:
vd_old = cell2mat(reshape(get([hBar.Face],'VertexData'),1,1,[]));
% Rearrange VertexData:
nB = numel(hBar);
vd_new = cell2mat(permute(mat2cell(vd_old,3,repelem(4,nB),repelem(1,nB)),[1,3,2]));
% Assign the new VertexData back into the Bar objects' Edge and Face fields:
for indB = 1:nB
hBar(indB).Edge.VertexData = vd_new(:,:,indB);
hBar(indB).Face.VertexData = vd_new(:,:,indB);
end
最后,我们使用text 命令手动添加标签:
xOffset = 1;
for indB = 1:nB
text(double(vd_new(1,2:4:end,indB)) + xOffset, double(tmpY(2:4:end)), ...
string(vd_new(1,2:4:end,indB)),'VerticalAlignment','middle');
end
最终结果:
最终代码:
function q47978293
close all force;
y = [91.9 8.1 94.4 5.6; 84.9 15.1 90.12 9.88; 89.4 10.6 91.2 8.8; 72 28 50.9 49.1];
figure(47978293); set(gcf,'Position',[786,556,887,420]); hBar = barh(y,'grouped');
legend("group" + (1:4),'location','northeast');
drawnow;
% hold on; scatter(h(1).Face.VertexData(1,:), h(1).Face.VertexData(2,:));
% Obtain the old VertexData:
vd_old = cell2mat(reshape(get([hBar.Face],'VertexData'),1,1,[]));
% Rearrange VertexData:
nB = numel(hBar);
vd_new = cell2mat(permute(mat2cell(vd_old,3,repelem(4,nB),repelem(1,nB)),[1,3,2]));
% Assign the new VertexData back into the Bar objects' Edge and Face fields:
xOffset = 1; % < Adjust as you see fit
for indB = 1:nB
hBar(indB).Edge.VertexData = vd_new(:,:,indB);
hBar(indB).Face.VertexData = vd_new(:,:,indB);
try
text( y(indB,:) + xOffset, mean(reshape(vd_new(2,1:2:end,indB),2,[]),1,'double'), ...
string(vd_new(1,2:4:end,indB)),'VerticalAlignment','middle');
catch % Compatibility fix for R2016b & R2017a. Credit @SardarUsama
text( y(indB,:) + xOffset, mean(reshape(vd_new(2,1:2:end,indB),2,[]),1,'double'), ...
split(num2str(vd_new(1,2:4:end,indB))),'VerticalAlignment','middle');
end
end
end
注意:由于此解决方案的 hacky 特性,如果重新绘制图形(例如由于调整大小),条形颜色将恢复到其原始状态 -所以要确保改变颜色的部分是你做的最后一件事。
附言
R2017b release notes 声明现在应该正式支持此自定义(通过 Bar 对象的 CData 属性),但我无法让图例显示正确的颜色。如果您想尝试一下,只需使用以下命令 (R2017b+) 进行绘图:
barh(y,'grouped','FaceColor','flat','CData',lines(size(y,1)));