# How can I highlight the points lying between two lines in a ListPlot?

I have a list of numbers like the following:

list = Table[RandomInteger[1000], {i, 1000}];


And I plot them so:

ListPlot[list]


I have drawn the black lines on the plot myself. I'd like to have min and max variables as a function of y, which once set, produce these lines in the chart and highlight the data between the lines. How can I do this?

• No, I want the area between these two lines get highlighted with a color e.g light yellow so that I can understand the density of this range easily – Mohsen Afshin Jan 5 '13 at 9:52
• Please clarify your question as to whether the min and max variables mentioned are constants of the form y_min  and y_max , the slopes of lines through the origin, or possibly more complex functions that will plot as curves on the data plot. – m_goldberg Jan 5 '13 at 18:52
• @Mr.Wizard I've updated the chart with what I mean. By specified sections I mean in a given range what percent of data lies between lies and how can show these values on the chart? – Mohsen Afshin Jan 8 '13 at 20:49
• @MohsenAfshin I suggest you ask that as a new question, as its focus is entirely different from this one. In future, please do not move the goal posts after people have taken the effort to answer the question. It's probably ok if they're very closely related, but in this case, they're not. – rm -rf Jan 8 '13 at 20:58
• @Hypnotoad, I appreciated your note and revert the question back to the original one. Thanks. – Mohsen Afshin Jan 8 '13 at 21:05

I shall suppose that you want something like this:

The first step is to convert your data into the (x, y) specified form:

list = RandomReal[2, 1000];
list = MapIndexed[{#2[[1]], #} &, list];


Then define bound functions:

low  = 0.5 + Sin[#/150]/4 &;
high = 1.2 + Sin[#/100]/3 &;


Gather points according to these functions:

list2 = Sort @ GatherBy[list, low@# < #2 < high@# & @@ # &];


Plot the points and functions and display together with Show:

Show[
ListPlot[list2, PlotStyle -> {Red, Black}],
Plot[{low@x, high@x}, {x, 0, 1000}]
]

• When I change low and high to low = # &; high = 3 # &; it doesn't work, why? – Mohsen Afshin Jan 5 '13 at 18:32
• @Mohsen It works just as it should but those bound functions make no sense for this data. Try low = #/300 &; high = #/100 &; instead. – Mr.Wizard Jan 5 '13 at 18:39
• I prefer this syntax list2 = Sort@GatherBy[list, (low[#[[1]]] < #[[2]] < high[#[[1]]]) &]; – Murta Jan 5 '13 at 19:01
• @Murta that works too but I have Bracket Phobia so I like mine better. :^) – Mr.Wizard Jan 5 '13 at 19:08
• huahuahua.. Bracket Phobia is good.. :-) . Using Esc [[ Esc it's not so ugly, but ok!.. In your honor follows improved version list2 = Sort@GatherBy[list, low@#[[1]] < #[[2]] < high@#[[1]] &] – Murta Jan 5 '13 at 19:16

Maybe this :

-- Edit by MA ---

min[n_, minPercent_] = minPercent* n;
max[n_, maxPercent_] = maxPercent* n;

SeedRandom[6];
list = Table[RandomInteger[1000], {i, 1000}];

Manipulate[
ListPlot[{list, min[#, minPercent] & /@ Range[1000],
max[#, maxPercent] & /@ Range[1000]},
Filling -> {3 -> {2}}],
{minPercent, 0.0, 5.0}, {maxPercent, 0.0, 5.0}]


• How can I convert this to a demonstration so that by changing the sliders of min and max the chart changes? – Mohsen Afshin Jan 5 '13 at 9:56
• You can use Manipulate and change the slopes and intercepts (or more generally the curves) for min, max. Give it a try and come back if you get stuck. – b.gates.you.know.what Jan 5 '13 at 9:58
• The performance of the chart is a little slow when I change the minPercent and maxPercent. Can it be optimized? – Mohsen Afshin Jan 5 '13 at 10:17

A comment on performance...

The Manipulate in the answer works smoothly and promptly on my old iMac (which does have 12GB memory), so it's not easy to detect improvements in performance.

There are many techniques for optimizing dynamic interfaces in Mathematica, and so far I've learnt a couple.

First, switch off continuous updating:

Manipulate[ListPlot[
{list, min[#, minPercent] & /@ Range[1000],
max[#, maxPercent] & /@ Range[1000]},
Filling -> {3 -> {2}}],
{minPercent, 0.0, 5.0, ContinuousAction -> False},
{maxPercent, 0.0, 5.0, ContinuousAction -> False}]


This updates the display only when you release the slider.

A more interesting way is to use ControlActive and provide alternative displays for when a control is active:

Manipulate[
ControlActive[
ListPlot[{min[#, minPercent] & /@ Range[1000],
max[#, maxPercent] & /@ Range[1000]},
Filling -> {2 -> {1}}],
ListPlot[{list, min[#, minPercent] & /@ Range[1000],
max[#, maxPercent] & /@ Range[1000]},
Filling -> {3 -> {2}}]],
{minPercent, 0.0, 5.0},
{maxPercent, 0.0, 5.0}]


The list is plotted only when you stop moving the sliders.

I'm using a very poor computer, and I'm also getting some poor performance. The following helps a lot (Note that I'm picking up from b.gatessucks so evaluate his functions first):

Manipulate[Show[
plot,
Plot[{max[x, maxPercent], min[x, minPercent]}, {x, 1, 1000},
Filling -> {1 -> {2}}]],
{minPercent, 0.0, 5.0}, {maxPercent, 0.0, 5.0},
Initialization :> {plot = ListPlot[list]}]


That way, you only have to plot the thousand points once.

• Perfect performance, just why? – Mohsen Afshin Jan 5 '13 at 18:05
• @MohsenAfshin. Because this Manipulate only contructs the ListPlot graphic once in the initialization phase and not over and over again at each update. – m_goldberg Jan 5 '13 at 18:56
• @MohsenAfshin In addition to what m_goldberg described about not having to re-plot the points at every update, using Plot rather than ListPlot and lots of points to draw lines happens to be more efficient. This is because MMA's optimized Plot function just samples 157 points in this case, whereas ListPlot forces it to find and display all 1000 points. – VF1 Jan 5 '13 at 21:26