如何使水平条组具有相同的颜色?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使水平条组具有相同的颜色?相关的知识,希望对你有一定的参考价值。
我需要使用grouped
样式绘制水平条纹,以便属于每个组的所有条形图具有相同的颜色但与其他组不同(即顶部组的所有条形图都是红色,其下方的组 - 绿色,依此类推。 ..)。
另外,如何将值水平放在每个条形的顶部?如何控制这些值的位置?
这是我的代码:
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];
h = barh(y,'grouped');
job = {'group1','group2 ','group 3','group4'};
legend(job,'location','northeast');
这是我目前的数字:
这是一个黑客:
一次绘制1行的条形图,并使用NaN
s填充空间,同时为所有行指定单一颜色。绘制NaN
s将不会产生任何影响。
[ry, cy] = size(y); %Number of rows and columns of y
hold on;
for k = 1:ry
tmp = [NaN(k-1,cy); y(k,:); NaN(4-k,cy)]; %Filling with NaNs
h{k} = barh(tmp, 'FaceColor', rand(1,3)); %Plotting bar graph in random color
h{k} = h{k}(1); %Store handle of any of the rows (Required for legend)
end
job = {'group1', 'group2', 'group3', 'group4'}; %Required legend entries
legend([h{:}], job); %Default location is already 'northeast' (so can be skipped)
输出:
这是另一种黑客行为;在R2017b上测试。
您要求的难以做的原因是因为条形图中的每个组实际上是一个Quadrilateral
对象(即多边形)。例如,让我们采取第一个Bar
对象:
>> 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
中的点不是只读的,这意味着我们可以智能地“重新排列”VertexData
条形组的N
矩阵以获得所需的结果。这是一种方法(注意我将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表示现在应该正式支持这种定制(通过CData
对象的Bar
属性),但我无法获得显示正确颜色的图例。如果您想尝试一下,只需使用以下命令(R2017b +)绘图:
barh(y,'grouped','FaceColor','flat','CData',lines(size(y,1)));
这两个请求重叠使得一切都变得复杂,因为为每个组使用统一的颜色意味着使用需要另一种解决方法来解决男性栏文本工作的问题。这是代码:
y = [
91.90 8.10 94.40 5.60;
84.90 15.10 90.12 9.88;
89.40 10.60 91.20 8.80;
72.00 28.00 50.90 49.10
];
[rows,cols] = size(y);
n = NaN(rows,cols);
c = {'r' 'g' 'b' 'y'};
bh = cell(rows,1);
lh = cell(rows,1);
hold on;
for k = 1:rows
curr = n;
curr(k,:) = y(k,:);
bar = barh(curr,'FaceColor',c{k});
bh{k} = bar;
lh{k} = bar(1);
end
hold off;
legend([lh{:}],{'G1','G2','G3','G4'},'Location','southoutside');
yl = get(gca,'XLim');
yl_up = yl(2);
xoff = yl_up * 0.01;
set(gca,'XLim',[yl(1) (yl_up + (yl_up * 0.1))]);
set(gcf,'Units','normalized','Position',[0.1 0.1 0.8 0.8]);
for i = 1:numel(bh)
bh_i = bh{i};
for j = 1:numel(bh_i)
bh_ij = bh_i(j);
hx = bh_ij.YData + xoff;
hy = bh_ij.XData + bh_ij.XOffset;
text(hx,hy,num2str(hx.','%.2f'), ...
'FontSize',10, ...
'HorizontalAlignment','left', ...
'VerticalAlignment','middle');
end
end
这是输出:
以上是关于如何使水平条组具有相同的颜色?的主要内容,如果未能解决你的问题,请参考以下文章
如何使listView中的一行始终具有相同的颜色android