MATLAB, Filling in the area between two sets of data, lines in one figure
Asked Answered
S

4

43

I have a question about using the area function; or perhaps another function is in order... I created this plot from a large text file:

https://static.mcmap.net/file/mcmap/ZG-Ab5ovKRltXxgYNC2paV_nX7MoWVMrKnyx/img818/9519/iwantthisareafilledin.jpg

The green and the blue represent two different files. What I want to do is fill in the area between the red line and each run, respectively. I can create an area plot with a similar idea, but when I plot them on the same figure, they do not overlap correctly. Essentially, 4 plots would be on one figure.

I hope this makes sense.

Sultan answered 5/6, 2011 at 20:23 Comment(0)
P
58

Building off of @gnovice's answer, you can actually create filled plots with shading only in the area between the two curves. Just use fill in conjunction with fliplr.

Example:

x=0:0.01:2*pi;                  %#initialize x array
y1=sin(x);                      %#create first curve
y2=sin(x)+.5;                   %#create second curve
X=[x,fliplr(x)];                %#create continuous x value array for plotting
Y=[y1,fliplr(y2)];              %#create y values for out and then back
fill(X,Y,'b');                  %#plot filled area

enter image description here

By flipping the x array and concatenating it with the original, you're going out, down, back, and then up to close both arrays in a complete, many-many-many-sided polygon.

Palindrome answered 26/9, 2011 at 21:57 Comment(4)
One more tip concerning fliplr: If your vectors are nx1 but you need to plot them as an 1xn (for whatever reason), take the prime inside. i.e. yb = [y1',fliplr(y2')]. Not yb = [y1',fliplr(y2)'].Paternoster
Can we make the shade region filled with "+" or other different Marker?Zita
@ftxx Sure, if you want to populate the area between the two curves with a matrix, and then plot it with a "+" for a point marker.Palindrome
@MelB Got the code that didn't work? It should work for any set of points that's properly constructed.Palindrome
B
16

Personally, I find it both elegant and convenient to wrap the fill function. To fill between two equally sized row vectors Y1 and Y2 that share the support X (and color C):

fill_between_lines = @(X,Y1,Y2,C) fill( [X fliplr(X)],  [Y1 fliplr(Y2)], C );
Bushwhacker answered 17/5, 2013 at 19:59 Comment(2)
did nothing for linesPathic
@MelB, can you be more explicit?Bushwhacker
D
14

You can accomplish this using the function FILL to create filled polygons under the sections of your plots. You will want to plot the lines and polygons in the order you want them to be stacked on the screen, starting with the bottom-most one. Here's an example with some sample data:

x = 1:100;             %# X range
y1 = rand(1,100)+1.5;  %# One set of data ranging from 1.5 to 2.5
y2 = rand(1,100)+0.5;  %# Another set of data ranging from 0.5 to 1.5
baseLine = 0.2;        %# Baseline value for filling under the curves
index = 30:70;         %# Indices of points to fill under

plot(x,y1,'b');                              %# Plot the first line
hold on;                                     %# Add to the plot
h1 = fill(x(index([1 1:end end])),...        %# Plot the first filled polygon
          [baseLine y1(index) baseLine],...
          'b','EdgeColor','none');
plot(x,y2,'g');                              %# Plot the second line
h2 = fill(x(index([1 1:end end])),...        %# Plot the second filled polygon
          [baseLine y2(index) baseLine],...
          'g','EdgeColor','none');
plot(x(index),baseLine.*ones(size(index)),'r');  %# Plot the red line

And here's the resulting figure:

enter image description here

You can also change the stacking order of the objects in the figure after you've plotted them by modifying the order of handles in the 'Children' property of the axes object. For example, this code reverses the stacking order, hiding the green polygon behind the blue polygon:

kids = get(gca,'Children');        %# Get the child object handles
set(gca,'Children',flipud(kids));  %# Set them to the reverse order

Finally, if you don't know exactly what order you want to stack your polygons ahead of time (i.e. either one could be the smaller polygon, which you probably want on top), then you could adjust the 'FaceAlpha' property so that one or both polygons will appear partially transparent and show the other beneath it. For example, the following will make the green polygon partially transparent:

set(h2,'FaceAlpha',0.5);
Diphase answered 6/6, 2011 at 13:22 Comment(1)
This also looks very promising. I didn't think attempt a method such as this. I will update you when I have my attempt.Sultan
C
5

You want to look at the patch() function, and sneak in points for the start and end of the horizontal line:

x = 0:.1:2*pi;
y = sin(x)+rand(size(x))/2;

x2 = [0 x 2*pi];
y2 = [.1 y .1];
patch(x2, y2, [.8 .8 .1]);

If you only want the filled in area for a part of the data, you'll need to truncate the x and y vectors to only include the points you need.

Christenechristening answered 5/6, 2011 at 23:34 Comment(2)
Thank you, I will look into this patch function today!Sultan
patch() is the lower-level version of fill() so either this or gnovice's answer should do what you want.Christenechristening

© 2022 - 2024 — McMap. All rights reserved.