Create a patch which includes all the histogram profiles

7 Ansichten (letzte 30 Tage)
Sim am 9 Mär. 2022
Bearbeitet: Sim am 11 Mär. 2022
Hi, I have several profiles/skylines of histograms:
hold on
for i = 1 : 10
X = normrnd(3000,10,[1,1000 ]);
histogram(X, 100 , 'DisplayStyle','stairs');
end
hold off
and I would like to create a patch which includes all the histogram profiles in this way (possibly, including the "highest" and the "lowest" lines/profiles, here in red):
Any idea?
1 Kommentar-1 ältere Kommentare anzeigen-1 ältere Kommentare ausblenden
Sim am 9 Mär. 2022
Hi, any suggestion here? :)

Melden Sie sich an, um zu kommentieren.

Akzeptierte Antwort

AndresVar am 10 Mär. 2022
If you can use uniform bin edges for all series then it can be simplified
Here it is plotting white over the another color. You can improve the fill method to draw a single polygon (instead of 2), so it's truly the patch area. (there many similar question about "shading between two curves")
see:
clear;
numSeries = 10; % number of histograms
X = normrnd(3000,10,[numSeries,1000]); % the data
% specify the bin edges (same for all series)
binLimits = [min(X(:)) max(X(:))];
binWdith = 0.8;
numBins = ceil(diff(binLimits)/binWdith);
% get counts and binEdges
counts = zeros([numSeries,numBins]);
for ii = 1 : size(X,1)
[counts(ii,:),binEdges]=histcounts(X(ii,:), 'BinLimits',binLimits,'BinWidth',binWdith);
end
% get top and bottom
counts_top = max(counts);
counts_bottom = min(counts);
% plot with 'BinCounts'
figure;
hold on;
histogram(BinEdges=binEdges,BinCounts=counts_top,FaceColor='m',LineStyle='none',FaceAlpha=0.3);
histogram(BinEdges=binEdges,BinCounts=counts_bottom,FaceColor='w',FaceAlpha=1,LineStyle='none');
% original histograms
for ii = 1:numSeries
histogram(X(ii,:),binEdges=binEdges,DisplayStyle="stairs");
end
hold off
title('using histogram')
% can also use fill
figure;
x=sort([binEdges(1:end-1) binEdges(2:end)]);
x=[x x(end) x(1)]; % close the polygon
y=[repelem(counts_top,2) 0 0]; % close with y=0
fill(x,y,'r');
hold on;
y=[repelem(counts_bottom,2) 0 0];
fill(x,y,'w');
title('using fill')
1 Kommentar-1 ältere Kommentare anzeigen-1 ältere Kommentare ausblenden
Sim am 10 Mär. 2022
Thanks a lot @AndresVar, an amazing solution!!! :)

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (1)

Sim am 10 Mär. 2022
Bearbeitet: Sim am 11 Mär. 2022
@AndresVar: I also got a solution.... it has a few bugs, but it works in the way I was thinking...
clear all; close all; clc;
% histograms, bin counts and bin edges
hold on
for i = 1 : 10
X = normrnd(3000,10,[1,1000 ]);
h = histogram(X, 10 ,'FaceColor',[0.7 0.7 0.7]);%, 'DisplayStyle','stairs');
y(:,i) = h.BinCounts;
x(:,i) = h.BinEdges;
end
% get coordinates of all the horizontal lines forming the histograms
k = 1;
for i = 1 : 10
xr = []; yr = []; l = [];
xr = repelem(x(:,i),2);
yr = repelem(y(:,i),2);
l = [xr(2:end-1) yr];
for j = 1 : 2 : size(l,1)-1
% line(l([j j+1],1),l([j j+1],2),...
% 'LineStyle','-','color',ColorOdrCustom(i,:), 'LineWidth',1);
% get the coordinates of all the lines
% | x_start | x_end | y_start | y_end |
lc(k,:) = [l(j,1) l(j+1,1) l(j,2) l(j+1,2)];
k = k + 1;
end
end
% Calculate the "external" curve and store the x1 and y1 coordinates
M = []; I = [];
[M,I] = min(lc(:,1));
s = lc(I,1); % start x
e = lc(I,2); % end x
v = lc(I,3); % value
% first point on the left
x1 = []; y1 = [];
x1(1) = s;
y1(1) = v;
k = 2;
while ~isempty(e)
f = []; M = []; I = []; m = [];
f = find(lc(:,1)>s & lc(:,1)<=e);
if max(lc(f,3)) >= v
m = []; M = []; I = [];
m = find(lc(f,3)>= v);
[M,I] = min(lc(f(m),1));
% if there are several left endpoints with the same x-value, take
% the "highest" one
if length(find(lc(f(m),1)==M)) > 1
lc2 = []; f2 = []; M2 = []; I2 = []; I = [];
lc2 = lc(f(m),:);
f2 = find(lc2(:,1)==M);
[M2,I2] = max(lc2(f2,3));
[~,I] = ismember(lc2(f2(I2),:),lc(f(m),:),'rows');
end
x1(k) = lc(f(m(I)),1); % store the x endpoint
y1(k) = y1(k-1); % store the y endpoint
x1(k+1) = x1(k); % store the replica x endpoint
y1(k+1) = lc(f(m(I)),3); % store the replica y endpoint
s = lc(f(m(I)),1); % start x
e = lc(f(m(I)),2); % end x
v = lc(f(m(I)),3); % value
k = k + 2;
else
f2 = [];
f2 = find(lc(f,1)<e & lc(f,2)>e);
M = []; I2 = []; I = [];
[M,I2] = max(lc(f(f2),3));
[~,I] = ismember(lc(f(f2(I2)),:),lc(f,:),'rows');
x1(k) = e; % store the x endpoint
y1(k) = y1(k-1); % store the y endpoint
x1(k+1) = x1(k); % store the replica x endpoint
if ~isempty(lc(f(I),3))
y1(k+1) = lc(f(I),3); % store the replica y endpoint
else
y1(k+1) = 0;
end
s = lc(f(I),1); % start x
e = lc(f(I),2); % end x
v = lc(f(I),3); % value
k = k + 2;
end
end
% Calculate the "internal" curve and store the x2 and y2 coordinates
M = []; I = [];
[M,I] = min(lc(:,1));
s = lc(I,1) % start x
e = lc(I,2) % end x
v = lc(I,3); % value
x2 = []; y2 = [];
x2(1) = e;
y2(1) = v;
k = 2;
while ~isempty(e)
f = []; M = []; I = []; m = [];
f = find(lc(:,1)<=e & lc(:,2)>e);
if all(lc(f,3) >= v)
M = []; I2 = []; I = [];
[M,I2] = min(lc(f,3))
[~,I] = ismember(lc(f(I2),:),lc(f,:),'rows')
x2(k) = x2(k-1); % store the x endpoint
if ~isempty(lc(f(I),3))
x2(k+1) = lc(f(I),2); % store the replica x endpoint
y2(k) = lc(f(I),3); % store the y endpoint
y2(k+1) = lc(f(I),3); % store the replica y endpoint
else
x2(k+1) = x2(k-1);
y2(k) = 0;
y2(k+1) = 0;
end
s = lc(f(I),1); % start x
e = lc(f(I),2); % end x
v = lc(f(I),3); % value
k = k + 2;
else
m = []; M = []; I = [];
m = find(lc(f,3)<= v);
[M,I] = min(lc(f(m),1));
x2(k) = lc(f(m(I)),1); % store the x endpoint
y2(k) = y2(k-1); % store the y endpoint
x2(k+1) = x2(k); % store the replica x endpoint
y2(k+1) = lc(f(m(I)),3); % store the replica y endpoint
s = lc(f(m(I)),1); % start x
e = lc(f(m(I)),2); % end x
v = lc(f(m(I)),3); % value
k = k + 2;
end
end
% add initial points to both curves
x1 = [x1(1) x1];
y1 = [0 y1];
x2 = [x2(1) x2];
y2 = [0 y2];
% plot both "external" and "internal" curves, together with the patch
plot(x1,y1,'-','LineWidth',2,'color','blue')
plot(x2,y2,'-','LineWidth',2,'color','red')
p1 = patch([x1 fliplr(x2)], [y1 fliplr(y2)], 'green');
p1.FaceAlpha = 0.1 ;
hold off
This is the result:
0 Kommentare-2 ältere Kommentare anzeigen-2 ältere Kommentare ausblenden

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Annotations finden Sie in Help Center und File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by