20
$\begingroup$

This question has appeared in various forms online, but I have not yet seen a complete answer, so I am posting it here.

More specifically, suppose I have a function

F: X->Y

that is not one-to-one. Mathematica can easily plot this function as follows:

Plot[F[x], {x, 0, 30}, PlotRange -> {{0, 30}, {0, 1}}]

This produces a graph that passes the vertical line test, but does not pass the horizontal line test, because F is not one-to-one. My question is, how do I get a plot of the inverse relation (which is not a function) for all Y?

Edit: I am adding the function F for clarity. I originally omitted it because I figured a generic solution would solve it.

F[x_] := (1000 * x) / 24279 * Sqrt[-1 + x^(2/7)]

Edit 2: I am adding the graph (that I am trying to graph the inverse relation of) I produced using Plot for further clarity.

enter image description here

To be clear, this image is produced by the following three commands:

F[x_] := (1000 * x) / (24279 * Sqrt[-1 + x^(2/7)])
myplot = Plot[F[x], {x,0,30}, PlotRange -> {{0,30}, {0,1}}]
Export["foo.png", myplot]
$\endgroup$
8
  • 1
    $\begingroup$ Have you used ParametricPlot yet? $\endgroup$
    – whuber
    Jan 29, 2013 at 4:16
  • 1
    $\begingroup$ That is a nice suggestion. I guess I could use X = T, Y = F[T], and that should do it. I didn't think of doing that before although I was aware of ParametricPlot. $\endgroup$
    – merlin2011
    Jan 29, 2013 at 4:23
  • $\begingroup$ @whuber, this does not quite work because F is not defined over all the real numbers, and I cannot compute the exact boundary of the domain of F. $\endgroup$
    – merlin2011
    Jan 29, 2013 at 4:30
  • $\begingroup$ That is, for certain values of T in my plot window, I get errors like "Infinite Expression 1/Sqrt[0.] encountered." $\endgroup$
    – merlin2011
    Jan 29, 2013 at 4:31
  • 1
    $\begingroup$ Related: mathematica.stackexchange.com/q/7859/5 and mathematica.stackexchange.com/q/7191/5 $\endgroup$
    – rm -rf
    Jan 29, 2013 at 6:43

3 Answers 3

27
$\begingroup$

Update:

Using the example function provided in op's update:

ff[x_] := (1000*x)/(24279*Sqrt[-1 + x^(2/7)]);

prmtrcplt1 = ParametricPlot[{x, ff[x]}, {x, 0, 30},
  PlotRange -> {{0, 30}, {0, 1}}, ImageSize -> 300, AspectRatio -> 1];

prmtrcplt2 = ParametricPlot[{ff[x], x}, {x, 0, 30},
  PlotRange -> Reverse[PlotRange[prmtrcplt1]], ImageSize -> 300,  AspectRatio -> 1];

Row[{prmtrcplt1, prmtrcplt2}, Spacer[5]]

enter image description here

plt = Plot[ff[x], {x, 0, 30}, PlotRange -> {{0, 30}, {0, 1}},ImageSize -> 300,
   AspectRatio -> 1];

ref1 = MapAt[GeometricTransformation[#, ReflectionTransform[{-1, 1}]] &, plt, {1}];

ref2 = plt /. line_Line :> GeometricTransformation[line, ReflectionTransform[{-1, 1}]];

Row[{plt, Graphics[ref1[[1]], PlotRange -> Reverse@PlotRange[ref1], ref1[[2]]],
  Graphics[ref2[[1]], PlotRange -> Reverse@PlotRange[ref2], ref2[[2]]]}, Spacer[5]]

enter image description here


original post

ParametricPlot (as suggested by whuber)

prmtrcplt1 = ParametricPlot[{x, x Sin[2 x]}, {x, -Pi, Pi},
   PlotRange -> {{-Pi, Pi}, {-3, 3}}, ImageSize -> 300];

prmtrcplt2 = ParametricPlot[{x Sin[2 x], x}, {x, -Pi, Pi},
  PlotRange -> {{-Pi, Pi}, {-3, 3}}, ImageSize -> 300];

Row[{prmtrcplt1, prmtrcplt2}, Spacer[5]]

enter image description here

Post-process using ReflectionTransform

reflected = plt /. line_Line :> {Red,  
     GeometricTransformation[line, ReflectionTransform[{-1, 1}]]};

Row[{plt, reflected, 
     Show[plt, Plot[x, {x, -Pi, Pi}, PlotStyle -> Black], reflected,
      PlotRange -> All, ImageSize -> 300]}, Spacer[5]]

enter image description here

Variations:

reflected2 = MapAt[GeometricTransformation[#, ReflectionMatrix[{-1, 1}]] &, plt, {1}];

reflected3 = MapAt[GeometricTransformation[#, ReflectionTransform[{-1, 1}]] &,plt, {1}]
$\endgroup$
4
  • $\begingroup$ ParametricPlot gives the error I mentioned above, RotationTransform as used above gives an empty graph, and I am trying ReflectionTransform. $\endgroup$
    – merlin2011
    Jan 29, 2013 at 5:35
  • $\begingroup$ @merlin2011, just saw your update with the specific form of F; will check what is needed to change to handle that case. Btw, what is the value of z in your definition of F (or was it meant to be x)? $\endgroup$
    – kglr
    Jan 29, 2013 at 5:50
  • $\begingroup$ meant to be x, will fix. $\endgroup$
    – merlin2011
    Jan 29, 2013 at 5:52
  • $\begingroup$ Can you apply the function Reverse in RelievePlot? I did unsuccessfully with Reverse[ReliefPlot[Cdata, PlotLegends -> Automatic, FrameTicks -> True, DataRange -> Automatic]]. $\endgroup$ Sep 23, 2016 at 10:02
20
$\begingroup$

From an earlier answer of mine:

axisFlip = # /. {
     x_Line | x_GraphicsComplex :> MapAt[# ~Reverse~ 2 &, x, 1],
     x : (PlotRange -> _) :> x ~Reverse~ 2
   } &;

Example of use:

F[x_] := (1000*x)/(24279*Sqrt[-1 + x^(2/7)])
myplot = Plot[F[x], {x, 0, 30}, PlotRange -> {{0, 30}, {0, 1}}]

myplot // axisFlip

Mathematica graphics

One of the nice things about this method is the ability to easily use Filling:

Plot[{Sin[x], .5 Sin[2 x]}, {x, 0, 2 \[Pi]}, Filling -> {1 -> {2}}] // axisFlip

Mathematica graphics

$\endgroup$
6
  • $\begingroup$ Your answer is wonderful! But the figure after axisFlip cannot Show with other figures. $\endgroup$ Oct 28, 2014 at 4:04
  • $\begingroup$ @EdenHarder It works fine here. Please try this example: g1 = Plot[{Sin[x], .5 Sin[2 x]}, {x, 0, 2 \[Pi]}, Filling -> {1 -> {2}}] // axisFlip; g2 = Plot[1 + 5 Sinc[10 x], {x, -1, 1}]; Show[g1, g2]. $\endgroup$
    – Mr.Wizard
    Oct 28, 2014 at 6:20
  • $\begingroup$ Please try this example: g1 = Plot[{Sin[x], .5 Sin[2 x]}, {x, 0, 2 \[Pi]}, Filling -> {1 -> {2}}] // axisFlip; g2 = Plot[1 + 5 Sinc[10 x], {x, -2, 2}, Filling -> Bottom]; Show[g1, g2, PlotRange -> {{-2, 2}, {0, 7}}] $\endgroup$ Oct 28, 2014 at 9:16
  • $\begingroup$ @Eden That works too, unless you are referring to the clipping in g2 which may be corrected by adding PlotRange -> All. Result: i.stack.imgur.com/9znY4.png Are you seeing something else? $\endgroup$
    – Mr.Wizard
    Oct 28, 2014 at 9:25
  • $\begingroup$ Yeah, it works! But why PlotRange -> All is needed? $\endgroup$ Oct 29, 2014 at 1:33
1
$\begingroup$

This is an ill formed sketch of an idea, but by allowing the output value of your function to be a set you can still maintain a 1 to 1 mapping.

Define a multi valued function:

g[x_] := {2 x} /; x < 10
g[x_] := {2 x, x} /; 10 <= x <= 20
g[x_] := {2 x, x, Sin@x} /; x > 20

A function to list plot a multi-valued function:

Clear@multiValueListPlot
multiValueListPlot[f_, {start_, stop_, step_: 100}] := 
 Function[{x, ys}, 
    Point[{x, #}] & /@ ys] @@@ ({#, f@#} & /@ 
     Range[start, stop, (stop - start)/step]) // Graphics

Show[multiValueListPlot[g, {1, 40, 300}], Frame -> True]

Mathematica graphics

For square roots:

Show[multiValueListPlot[y /. Solve[y^2 == #] &, {0, 40, 300}], 
 Frame -> True, FrameLabel -> {"X", "Square Roots"}]

Mathematica graphics

$\endgroup$

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.