Plotting different colored line based on condition(s)
73 views (last 30 days)
Show older comments
Hello: I am attempting to plot a line that changes colors (between red and green) based upon the value of the data. For example, if I have x=1:1:5 and corresponding y=[-2,-1,1,2,3], I would like the plot to have a red line when y is negative and a green line when y is positive and have a corresponding legend to denote this. P.S. my actual data series is much longer than (5) values so a looping code would be preferable.
0 Comments
Accepted Answer
Chad Greene
on 6 Oct 2020
Edited: Chad Greene
on 6 Oct 2020
What if you create two lines and plot them separately?
x = 0:1000;
y = sind(x);
% duplicate:
y_red = y;
y_red(y>0) = NaN;
y_green = y;
y_green(y<0) = NaN;
figure
plot(x,y_red,'r','linewidth',2)
hold on
plot(x,y_green,'g','linewidth',2)
2 Comments
Adam Danz
on 6 Oct 2020
Edited: Adam Danz
on 6 Oct 2020
This is the best method when the x values are already known at y=0. It's simple, effective, and quick. But if the x coordinates are not known when y=0, you'll need to compute them and insert them into the (x,y) vectors.
For example, try approach solution when x = 22:45:1080.
More Answers (1)
Adam Danz
on 6 Oct 2020
Edited: Adam Danz
on 6 Oct 2020
A line object can only have 1 color. To change the color of values above and below y=0 you have to break up your line into segments. This is relatively easy if you already have y-coordinates at (or very close to) zero and can be solved by simple logical indexing.
However if line segments pass through y=0 you must compute the x-coordinates where y equals 0 and insert those coordinates into your (x,y) vectors.
Here's a demo that steps through that process.
% Define coarse (x,y) coordinates that pass through y=0
x=1:1:15;
y=[-2,-1,1,2,3];
y = [y,fliplr(y),y];
% Plot the original data
figure()
plot(x,y,'b-o','LineWidth',2)
yline(0)
% Get the index of each coordinate just prior to passing y=0 (startSegIdx)
signDiff = [0,diff(sign(y(:)'))];
startSegIdx = unique([find(signDiff(:)'==2)-1, find(signDiff(:)'==-2)-1])
% For each segment that passes through y=0, compute equation
% of the line and solve for y=0
x0 = nan(size(startSegIdx));
for i = 1:numel(startSegIdx)
coeffs = polyfit(x(startSegIdx(i)+[0,1]), y(startSegIdx(i)+[0,1]), 1);
x0(i) = -coeffs(2)/coeffs(1);
end
% (x0,y0) are the y== crossing points. Add those points to the plot
% to check for accuracy
figure()
plot(x,y,'b-o','LineWidth',2)
yline(0)
hold on
plot(x0,zeros(size(x0)),'m*','MarkerSize', 12,'LineWidth',2)
% Insert the new (x0,y0) coordinates in the correct incides of (x,y)
repNum = ones(size(x));
repNum(startSegIdx) = 2;
xNew = repelem(x(:).',1,repNum(:)');
xNew(startSegIdx + (1:numel(startSegIdx))) = x0;
yNew = repelem(y(:).',1,repNum(:)');
yNew(startSegIdx + (1:numel(startSegIdx))) = 0;
% Plot the new line to make sure it matches the old one, plus the 0-crossings
figure()
plot(x,y,'b-o','LineWidth',2)
yline(0)
hold on
plot(x0,zeros(size(x0)),'m*','MarkerSize', 12,'LineWidth',2)
plot(xNew, yNew, 'r:o', 'LineWidth', 1, 'MarkerSize', 16)
% Break up the (xNew,yNew) line into segments below/above y=0
% There will be 1 segment for each time it crosses y=0
% 1. Duplicate values at x=0
segmentSub = unique(find(sign(yNew(:)')==0));
repNum2 = ones(size(xNew));
repNum2(segmentSub) = 2;
xSeg = repelem(xNew, 1, repNum2);
ySeg = repelem(yNew, 1, repNum2);
% create a grouping variable for each element of (xSeg, ySeg) that identifies its segment.
segmentSub2 = [segmentSub + (0:numel(segmentSub)-1), numel(xSeg)];
group = repelem(1:numel(segmentSub2),diff([0,segmentSub2]));
% Plot the line segments
figure()
hold on % important
h = splitapply(@(x,y)plot(x,y,'-o','LineWidth',1),xSeg,ySeg,group);
% Color segment based on the sign of y values
isPositive = arrayfun(@(h)any(h.YData > 0),h);
set(h(isPositive), 'Color', 'g')
set(h(~isPositive), 'Color', 'r')
% add ref line
yline(0)
0 Comments
See Also
Categories
Find more on Annotations in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!