How to plot discrete array with colors

12 次查看(过去 30 天)
Laura
Laura 2023-6-20
编辑: dpb 2023-6-21
I have 'nodes' which each have a status. The status of these nodes are contained in an array 'status_array' and have the values "waiting" or "busy". I would like to plot an array with colors indicating what state each node is in, for example, green = 'waiting' and red = 'busy'. This way I can visualize how the node transistion from their states. I want it to look something like this:
I tried using imagesc or bar but it doesn't look quite right.
Thanks in advance for any suggestions!

回答(3 个)

Star Strider
Star Strider 2023-6-20
One approach —
status = randi([0 1], 1, 9) % 'Waiting' = 0, 'Busy' = 1
status = 1×9
0 0 0 1 0 1 0 0 1
status = flip(status);
cv = ["g" "r"]; % Coluur Vector
xv = repmat([0 1], size(status,2), size(status,1));
yv = xv + (0:size(status,2)-1).';
figure
% patch([xv fliplr(xv)], [yv fliplr(yv)], cv(status+1))
hold on
for k = 1:numel(status)
patch([xv(k,:) fliplr(xv(k,:))], [[1 1]*yv(k,1) [1 1]*(yv(k,2))], cv(status(k)+1))
end
hold off
xlim([0 0.1])
% axis('equal')
daspect([0.1 1 1])
xticks([])
yt = yticks;
yticks(0.5:max(yt))
yticklabels(yt(2:end))
I could not get this to work correctly without the loop.
.
  1 个评论
dpb
dpb 2023-6-20
编辑:dpb 2023-6-20
I didn't go back to the beginning to try to remove the loop there, but it's not terribly difficult to then update the graphic to match a new status vector without looping...
Following copies the above with one exception during creation -- save a vector of patch handles, hP, to use to address the objects later.
status = randi([0 1], 1, 9) % 'Waiting' = 0, 'Busy' = 1
status = 1×9
0 0 0 0 0 0 1 0 0
status = flip(status);
cv = ["g" "r"]; % Coluur Vector
xv = repmat([0 1], size(status,2), size(status,1));
yv = xv + (0:size(status,2)-1).';
figure
hold on
hP=gobjects(size(status)); % patch handles array
for k = 1:numel(status)
hP(k)=patch([xv(k,:) fliplr(xv(k,:))], [[1 1]*yv(k,1) [1 1]*(yv(k,2))], cv(status(k)+1));
end
hold off
xlim([0 0.1])
daspect([0.1 1 1])
xticks([])
yt = yticks;
yticks(0.5:max(yt))
yticklabels(yt(2:end))
Above ends the original iwth the one mod noted...now update given a new status...but, the .FaceColor property is actually an RGB triplet; the patch() function will accept the shortnames for the base colors but have to use rgb to set directly...
% define the rgb triplets to go with the original colors
R=[1 0 0]; G=[0 1 0]; CV=[G;R]; % lookup vector to match "g","r"
status = randi([0 1], 1, 9); % a new status vector
status=flip(status); % match order to object handle order
cv(status+1) % what what it is for comparison in string form
ans = 1×9 string array
"r" "r" "r" "r" "g" "r" "r" "g" "r"
set(hP,{'FaceColor'},num2cell(CV(status+1,:),2)) % update the colors to match
Remember to look at the colors in comparison to the color names from bottom up, not top down!!! :)

请先登录,再进行评论。


Askic V
Askic V 2023-6-20
I would also like to offer my solution. It is not so elegant comparing to @Star Strider, but it can show you how bar can be used to achieve something similar:
clear;clc;close all;
red = [1 0 0];
green = [0 1 0];
% Example data
data = [1; 0; 1; 0; 0; 1; 1; 0; 1];
% Adjust the width of the bars
barWidth = 0.8; % Specify the desired width of the bars
barWidthRatio = barWidth / numel(data); % Calculate the ratio of the desired width to the number of bars
h = bar(1, ones(size(data, 1), 1), 'stacked');
for i = 1:numel(data)
h(i).BarWidth = barWidthRatio;
if data(i) == 1
h(i).FaceColor = green;
else
h(i).FaceColor = red;
end
text(0.95, i, num2str(i), 'HorizontalAlignment', 'right', 'VerticalAlignment', 'bottom');
end
axis ij; % invert axis
ylabel('Value');
ylim([0 size(data, 1)+1]);
yticks(1:size(data, 1)); % Set the y-axis tick locations
yticklabels([]); % Hide the y-axis tick labels

dpb
dpb 2023-6-20
编辑:dpb 2023-6-21
I looked at the vectorized version issue a little -- it doesn't work easily for the purpose because even if you create multiple polygons, it's then a one-object patch with only a single .FaceColor property. To set the colors by face then have to set the initial color vector as a nx1x3 rgb array which is more of a pain to generate than the lookup of the color vector or 2D array.
While doable and does create the same overall effect, I think it's handier to leave it as the separate patch objects above -- although I guess once one writes the code once, even if it was harder initially, then it doesn't really matter to use...
The following works...
status=randi(2,[1,9])-1;
status=flip(status);
status
status = 1×9
1 0 1 0 1 1 0 1 0
x=[0 1 1 0].'; y=[0 0 1 1].';
x=repmat(x,size(status));
y=repmat(y,size(status))+[0:numel(status)-1];
G=[0 1 0];G=reshape(G,1,1,[]);
R=[1 0 0];R=reshape(R,1,1,[]);
C=[G; R];
c=C(status+1,1,:);
hP=patch(x,y,c);
box on
xlim([0 0.1])
daspect([0.1 1 1])
prior to the cleanup of tick labels, etc., ...

类别

Help CenterFile Exchange 中查找有关 Polygons 的更多信息

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by