8

I have a list of numbers like the following:

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

And I plot them so:

ListPlot[list]

enter image description here

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?

Mohsen Afshin
  • 985
  • 1
  • 5
  • 17
  • 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 05 '13 at 09: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 05 '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 08 '13 at 20:49
  • 1
    @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 08 '13 at 20:58
  • @Hypnotoad, I appreciated your note and revert the question back to the original one. Thanks. – Mohsen Afshin Jan 08 '13 at 21:05

4 Answers4

11

I shall suppose that you want something like this:

Mathematica graphics

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}]
]
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • When I change low and high to low = # &; high = 3 # &; it doesn't work, why? – Mohsen Afshin Jan 05 '13 at 18:32
  • 1
    @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 05 '13 at 18:39
  • I prefer this syntax list2 = Sort@GatherBy[list, (low[#[[1]]] < #[[2]] < high[#[[1]]]) &]; – Murta Jan 05 '13 at 19:01
  • 1
    @Murta that works too but I have Bracket Phobia so I like mine better. :^) – Mr.Wizard Jan 05 '13 at 19:08
  • 3
    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 05 '13 at 19:16
  • @Mohsen I see you Accepted my answer. Thank you. Please note that the Sort I used may be unstable in your application. As written it simply sorts the points gathered by how many there are; that is, the area with the fewer points will be colored red, but if the area to be highlighted actually has more points in it than not it will flip. You may want to use something like SortBy[(* gather *), #[[1, 2]]&] instead. Should you have any trouble with this please ask and I'll assist. – Mr.Wizard Jan 08 '13 at 06:53
  • Thank you @Mr.Wizard, don't have you any solution to the Updated section of the question? – Mohsen Afshin Jan 08 '13 at 07:49
  • @Mohsen Sorry, I didn't see that until now. I'm about to sleep though, so I'll take a look tomorrow. – Mr.Wizard Jan 08 '13 at 10:18
7

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}]

enter image description here

Mohsen Afshin
  • 985
  • 1
  • 5
  • 17
b.gates.you.know.what
  • 20,103
  • 2
  • 43
  • 84
5

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.

cormullion
  • 24,243
  • 4
  • 64
  • 133
5

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.

VF1
  • 4,702
  • 23
  • 31
  • Perfect performance, just why? – Mohsen Afshin Jan 05 '13 at 18:05
  • 2
    @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 05 '13 at 18:56
  • 2
    @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 05 '13 at 21:26