8
$\begingroup$

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?

$\endgroup$
5
  • $\begingroup$ 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 $\endgroup$ Commented Jan 5, 2013 at 9:52
  • $\begingroup$ 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. $\endgroup$
    – m_goldberg
    Commented Jan 5, 2013 at 18:52
  • $\begingroup$ @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? $\endgroup$ Commented Jan 8, 2013 at 20:49
  • 1
    $\begingroup$ @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. $\endgroup$
    – rm -rf
    Commented Jan 8, 2013 at 20:58
  • $\begingroup$ @Hypnotoad, I appreciated your note and revert the question back to the original one. Thanks. $\endgroup$ Commented Jan 8, 2013 at 21:05

4 Answers 4

11
$\begingroup$

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}]
]
$\endgroup$
8
  • $\begingroup$ When I change low and high to low = # &; high = 3 # &; it doesn't work, why? $\endgroup$ Commented Jan 5, 2013 at 18:32
  • 1
    $\begingroup$ @Mohsen It works just as it should but those bound functions make no sense for this data. Try low = #/300 &; high = #/100 &; instead. $\endgroup$
    – Mr.Wizard
    Commented Jan 5, 2013 at 18:39
  • $\begingroup$ I prefer this syntax list2 = Sort@GatherBy[list, (low[#[[1]]] < #[[2]] < high[#[[1]]]) &]; $\endgroup$
    – Murta
    Commented Jan 5, 2013 at 19:01
  • 1
    $\begingroup$ @Murta that works too but I have Bracket Phobia so I like mine better. :^) $\endgroup$
    – Mr.Wizard
    Commented Jan 5, 2013 at 19:08
  • 3
    $\begingroup$ 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]] &] $\endgroup$
    – Murta
    Commented Jan 5, 2013 at 19:16
7
$\begingroup$

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

$\endgroup$
3
  • $\begingroup$ How can I convert this to a demonstration so that by changing the sliders of min and max the chart changes? $\endgroup$ Commented Jan 5, 2013 at 9:56
  • $\begingroup$ 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. $\endgroup$ Commented Jan 5, 2013 at 9:58
  • 1
    $\begingroup$ The performance of the chart is a little slow when I change the minPercent and maxPercent. Can it be optimized? $\endgroup$ Commented Jan 5, 2013 at 10:17
5
$\begingroup$

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.

$\endgroup$
5
$\begingroup$

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.

$\endgroup$
3
  • $\begingroup$ Perfect performance, just why? $\endgroup$ Commented Jan 5, 2013 at 18:05
  • 2
    $\begingroup$ @MohsenAfshin. Because this Manipulate only contructs the ListPlot graphic once in the initialization phase and not over and over again at each update. $\endgroup$
    – m_goldberg
    Commented Jan 5, 2013 at 18:56
  • 2
    $\begingroup$ @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. $\endgroup$
    – VF1
    Commented Jan 5, 2013 at 21:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.