27
$\begingroup$

Consider the plot of this discontinuous function:

f[x_] := If[2 < x < 3, 0, x]
Plot[f[x], {x, 0, 5}]

plot of a discontinuous function

I'd like to plot that without the vertical segments. Modifying the function f is not allowed.

ADDED: I should've said more about the restriction on modifying f. In the real application where this came up, f is a messy thing that should be treated as a black box. So we can't pick out the discontinuity, and probably can't invert the function either.

$\endgroup$
3
  • $\begingroup$ These are amazing answers; thanks so much everyone! $\endgroup$
    – dreeves
    Dec 8, 2010 at 6:54
  • $\begingroup$ see here for Mathematica Q&A: Excluding Points from Plots (from Wolfram) $\endgroup$
    – user1066
    Mar 15, 2011 at 10:28
  • 3
    $\begingroup$ Is this the community's first question? $\endgroup$
    – LCarvalho
    Dec 23, 2017 at 7:18

7 Answers 7

25
$\begingroup$

I looked for a way without redefining the function and not using explicit knowledge about it (so it can be generalized)

pl[f_, lims_] := Module[{eps = 0.05},
   Off[InverseFunction::"ifun"];
   Print@Plot[f[u], {u, lims[[1]], lims[[2]]},
      Exclusions ->
       {{f[u] == f[InverseFunction[f][u]], Abs[(f[u] - f[u + eps])] > 10 eps},
        {f[u] == f[InverseFunction[f][u]], Abs[(f[u] - f[u - eps])] > 10 eps}}]
    On[InverseFunction::"ifun"];
   ];

(* Testing *)

f[x_] := If[2 < x < 3, 0, x];
pl[f, {0, 5}];
pl[Tan, {0, 2 Pi}]

Mathematica graphics

Edit

Ok, this one does not use InverseFunction, and identifies discontinuities, as far as I tested it:

(*Function Definition*)
pl[f_, lims_]:= Plot[f[u],{u, lims[[1]], lims[[2]]},Exclusions->{True, f[u] == 1}];

(*--------Test--------*)
flist = {
   If[Abs@Sin@# > .5, 1, 0] &,
   If[2 < # < 3, 0, #] &,
   1/Sin@# + 1 &,
   Tan};
pk = Table[{Plot[fun[x], {x, 0, 10}], pl[fun, {0, 10}]}, {fun, flist}];
GraphicsGrid[pk]

Here are side by side the results from Plot (without Options) and from this function:

alt text

Edit 2

Found a counterexample, and perhaps some comprehension about what is going on there.

   f = If[Abs@Sin@# > .5, 2, 5] &  

Does not work. Why? It's easy ... the discontinuity does not cross f[u]==1 ...

Doing a Reap-Sow on the Plot (as in @rcollyer's answer) I saw that adding the Exclusions with f[u]==1 adds a few points to the trace just around f[u]==1 and seems that that is the trigger for excluding the discontinuities from the domain.

Now trying to find a way to change the f[u]==1 for something that works better ...

Edit 3

Found a way with a discrete derivative, a tricky thing.

Like this:

(*Function Definition*)
pl[f_, lims_]  :=  Plot[f[u], {u, lims[[1]], lims[[2]]},
                              Exclusions -> {(f[u] - f[u + .1])/.1 == 10, 
                                             (f[u] - f[u + .1])/.1 == -10}];  

Note two issues:

  1. I had to remove the "True" or "Automatic" option from the Exlusions
  2. Taking Abs[] for joining the two Exclusion equalities does not work since it's monitoring the evolution of the lhs ...
$\endgroup$
11
  • $\begingroup$ Okay, simple question: why does the addition of f[u]==1 help? Exclusions -> True, alone, does not work, so why does the addition of the function work? I'm honestly confused. BTW: +1, simple and clever. $\endgroup$
    – rcollyer
    Dec 8, 2010 at 12:28
  • $\begingroup$ Wow, this seems like a definitive improvement to Plot itself. My only reservation about it is what happens when the function is not invertible... $\endgroup$
    – dreeves
    Dec 8, 2010 at 15:37
  • 1
    $\begingroup$ @dreeves I am not using InverseFunction anymore. And trig functions are not invertible ... I am still trying to find a counterexample where this doesn't work, since I am not blind-confident about the method. $\endgroup$ Dec 8, 2010 at 20:10
  • 1
    $\begingroup$ @rcollyer I was experimenting a lot. I really do not understand why this work, but I am still not able to find a counter-example. $\endgroup$ Dec 8, 2010 at 20:12
  • $\begingroup$ @belisarius, per edit 2, changed the exclusion to f[u]==u and it only excluded the second and third discontinuity. So, you're definitely on to something. My thinking is that you'll need to know a little about the domain/range of your function in order to properly set up the exclusions, i.e. plot it without the exclusions first. $\endgroup$
    – rcollyer
    Dec 9, 2010 at 4:36
16
$\begingroup$

The answer is Exclusions as follows:

alt text

In this case, your excluding the points where there are discontinuities. It will also accept functional definitions.

Edit: Since you state you can't pick out the exclusions, I assume you mean that unlike the example you gave the exclusions are not known a priori. And, assuming that InverseFunction does not work for you, as per belisarius's solution, then you will have to generate them "by hand". The best bet would be to use EvaluationMonitor to acquire the points Plot uses, like in the example

data = Reap[Plot[Sin[x], {x, 0, 2 Pi}, EvaluationMonitor :> Sow[{x, Sin[x]}]] ][[-1, 1]]

and compare the numerical derivatives on both sides of each point

der = (Subtract@@#[[All,2]])/(Subtract@@#[[All,1]])
Select[Partition[data, 3, 1], Abs[ der@#[[{1,2}]] - der@#[[{2,3}]] ] > tol& ]

where the difference exceeds some tolerance. You'll need to then pull out the offending point, but it should be the only one that exists in 3 consecutive sublists. This then gives you your exclusions.

Edit, part 2: In the continuing jockeying for the "correct" solution to this, I found in the Applications section of the Plot documentation a method that is effective for all of the inital tests used by @belisarius: Exclusions -> {1/f[x] == 0}, and Exclusions -> {1/D[f,x] == 0} works for my pathological example of Sin[1/x^2]. Unfortunately, both still fail for If[Abs@Sin@# > .5, 2, 5]&. Additionally, the use of the derivative fails for all of the initial tests and spuriously removes pieces when combined with 1/f[x]==0.

$\endgroup$
4
  • $\begingroup$ Here is another nice way to find the discontinuities forums.wolfram.com/mathgroup/archive/2009/Aug/msg00387.html. The first function def lacks the "==" sign before the "z" $\endgroup$ Dec 8, 2010 at 6:40
  • $\begingroup$ It should be noted that Select is calculating something close to the second derivative (en.wikipedia.org/wiki/…), and it may be simpler to think of it in those terms. $\endgroup$
    – rcollyer
    Dec 8, 2010 at 12:23
  • $\begingroup$ Can something like this be adapted for a ListPlot, where you have discrete samples of the function? I want to exclude points that are near a discontinuity (because the samples here are very unreliable) $\endgroup$
    – a06e
    Mar 16, 2017 at 0:06
  • 1
    $\begingroup$ @becko you'll have to mask them yourself. Although, I'd exchange the problematic points for Missing[] as ListPlot will produce something similar to Exclusions in that case. $\endgroup$
    – rcollyer
    Mar 16, 2017 at 15:00
10
$\begingroup$

This works:

f[x_] := Piecewise[{{x, x < 2}, {0, x < 3}, {x, x > 3}}]
Plot[f[x], {x, 0, 5}]

and you also have the advantage that Piecewise is derivable (see docs).

EDIT: But if you can not change f, then you can do this:

Plot[ f[x], {x, 0, 5}, Exclusions -> {2, 3} ]
$\endgroup$
7
  • $\begingroup$ Thanks, good answer, though note the restriction that I don't want to modify the function f. $\endgroup$
    – dreeves
    Dec 8, 2010 at 0:49
  • $\begingroup$ Oops. rcollyer posted his answer while I added Exclusions to mine. :-) $\endgroup$ Dec 8, 2010 at 0:54
  • $\begingroup$ @gdelfino: it took me a few moments to find it and generate the graphs. $\endgroup$
    – rcollyer
    Dec 8, 2010 at 0:56
  • $\begingroup$ @gdelfino, I was trying to imply that if it hadn't taken me that long, I would have posted it much sooner. But, it seems that I completely missed that point in my comment. $\endgroup$
    – rcollyer
    Dec 8, 2010 at 20:40
  • $\begingroup$ @rcollyer Thank's fine. It is incredible how fast people answer good questions in stackoverflow. $\endgroup$ Dec 9, 2010 at 12:24
10
$\begingroup$

As pointed out by Wolfram, the following will also work. Not as powerful as Exclusions or Piecewise, of course:

f[x_] := If[2 < x < 3, 0, x]
Plot[f[x], {x, 0, 2, 3, 5}]

Update: This code might have worked in earlier versions of Mathematica. As of version 11, it does not work anymore.

$\endgroup$
5
  • $\begingroup$ +1 One of those features I usually forget about ... $\endgroup$ Dec 9, 2010 at 18:35
  • $\begingroup$ +1 I cannot recall seeing this before. $\endgroup$
    – Mr.Wizard
    Mar 4, 2011 at 9:37
  • $\begingroup$ Checking back,I found out about this in the following Mathmergency video. Not, as I thought, a Wolfram presentation. $\endgroup$
    – user1066
    Mar 4, 2011 at 16:40
  • 1
    $\begingroup$ @Mr.Wizard Does this still work? On v11 I get a weird output: System`ProtoPlotDump`iPlot[Plot, System`ProtoPlotDump`obj$1974, f[x], {x, 0, 2, 3, 5}] $\endgroup$
    – a06e
    Mar 16, 2017 at 0:08
  • $\begingroup$ @becko It fails in version 10.1 as well. Likely it was experimental syntax that was rejected. $\endgroup$
    – Mr.Wizard
    Mar 16, 2017 at 5:53
3
$\begingroup$

To answer your original question, (I assume you have your reasons for not using the Piecewise solution given by gdelfino)

f[x_]:=If[2<x<3,0,x]
Plot[f[x],{x,0,5},Exclusions->{2,3}]
$\endgroup$
2
$\begingroup$

Maybe I am getting late here, but in Mathematica 11 (and perhaps earlier versions) the ExclusionsStyle option would do the job, also for arbitrary functions...

f[x_] := If[2 < x < 3, 0, x]
Plot[f[x], {x, 0, 5}, ExclusionsStyle -> None]

Another example that also works

f[x_] := Tan[x]
Plot[f[x], {x, 0, 2 \[Pi]}, ExclusionsStyle -> None, PlotRange -> {-20, 20}]
$\endgroup$
1
$\begingroup$

This definitely comes late, but I think another elegant solution is to use in place of Plot[f[x], {x, 0, 5}] the instruction

DiscretePlot[f[x], {x, 0, 5, 0.1}, PlotStyle -> "LineColor" -> None]

The result of DiscretePlot

I know it doesn't exactly answer the question, but for illustrative purposes it may be more than enough. For functions defined via NIntegrate[] and not known in closed form, moreover, all the above solutions fail because conditions like Exclusions -> {1/f[x] == 0} do not work.

$\endgroup$

Your Answer

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

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