1
$\begingroup$

How do I use both ScalingFunctions and PlotRange with ListLinePlot. It seems that the moment I use ScalingFunctions, PlotRange is completely ignored.

Example:

ListLinePlot[
 {6, 28, 75},
 ScalingFunctions -> {"Log2", None},
 PlotRange -> {{0, 20}, Automatic}
 ]

The plot I get has an x-axis that ranges from 1 to 3. I want 0 to 20.

I know that I can change the range of x values in plotting functions like ListLinePlot with DataRange, but that doesn't help me. I want to extend the range of the x-axis slightly beyond the range of the data values.

$\endgroup$
  • 2
    $\begingroup$ I think your problem stems from the inclusion of $0$ in the range for a logarithmic axis, which probably causes the rest of the PlotRange specification to be ignored. Try using a small non-zero value instead. More in general, your purpose could be more appropriately achieved using PlotRangePadding as well. $\endgroup$ – MarcoB Jun 10 '17 at 12:38
  • $\begingroup$ You're right. If I start the plot range from 1, the problem goes away. PlotRangePadding doesn't really help me, because it's not padding I want. I want a constant plot range and use the code for different data sets, which may only have data points in some areas of the range. $\endgroup$ – mistercake Jun 10 '17 at 13:28
  • 1
    $\begingroup$ If you know the minimum x, or a lower bound, that you will encounter in your data sets, you could use that in PlotRange instead of 1 or 0. The number 0 corresponds to -Infinity on the Log2 scale, which cannot be plotted. $\endgroup$ – Michael E2 Jun 10 '17 at 14:28
3
$\begingroup$

I can explain what's happening. Fixing it can be done as @MarcoB explained in a comment, by passing positive numbers for the PlotRange. These could be determined in advance if all the data sets to be plotted are known. The basic usage rule to be added is this:

With any sort of log scaling, PlotRange settings that contain zero or negative numbers will be rejected and an Automatic setting will be used. This applies to any other sort of scaling, if the scaling of the plot range results in non-real intervals.

What's happening?

Plotting changes from version to version, so here is the version this explanation is based on:

$Version
(* "11.1.1 for Mac OS X x86 (64-bit) (April 18, 2017)"  *)

With the following code, you can track the changes to the plot range. First the automatic settings such as Automatic and Full are expanded to give a complete PlotRange setting of the form {{_, _}, {_, _}}. Next the ranges are scaled. We see that the first part of PlotRange -> {{0, 20}, Automatic} is scaled to {-∞, Log2[20]}. What happens next is this range setting is rejected if it contains ∞ | -∞ | _Complex | Indeterminate. It is then reset to Automatic, and the range recalculated, which results in the range based just on the data.

Block[{System`ProtoPlotDump`sPrint, prnt},
 SetAttributes[prnt, HoldAll];
 prnt[e_] := Module[{name, ok},
   ok = Quiet@ Check[name = SymbolName@Unevaluated@e; True, False];
   If[ok && StringMatchQ[name, ___ ~~ "range" ~~ ___],
     Print[HoldForm[e] -> e]]
   ];
 System`ProtoPlotDump`sPrint = prnt;
 ListLinePlot[{6, 28, 75}, ScalingFunctions -> {"Log2", None}, 
  PlotRange -> {{0, 20}, Automatic}]
 ]

Mathematica graphics

Interestingly, the range is not padded above, but it is if in the original call to ListLinePlot, the PlotRange option is omitted.

Block[{System`ProtoPlotDump`sPrint, prnt},
 SetAttributes[prnt, HoldAll];
 prnt[e_] := Module[{name, ok},
   ok = Quiet@Check[name = SymbolName@Unevaluated@e; True, False];
   If[ok && StringMatchQ[name, ___ ~~ "range" ~~ ___],
    Print[HoldForm[e] -> e]]
   ];
 System`ProtoPlotDump`sPrint = prnt;
 ListLinePlot[{6, 28, 75}, ScalingFunctions -> {"Log2", None}]
 ]

Mathematica graphics

Example workaround

Some sample data sets:

SeedRandom[1];  (* for reproducibility *)
foo = 4;
{data1, data2, data3} = Table[
   Transpose@
    {Sort@ RandomReal[2^{RandomReal[-4], RandomReal[4]}, foo],  (* x-coordinates *) 
     RandomReal[RandomReal[100], foo++]},                       (* y-coordinates *)
   {3}];

Calculate the minimum PlotRange:

pr = {MinMax[{data1, data2, data3}[[All, All, 1]]], All}
(*  {{0.186413, 7.90499}, All}  *)

Plot (similar to above, there is no padding; if desired, add padding manually):

ListLinePlot[{data1, data2, data3}, 
 ScalingFunctions -> {"Log2", None}, PlotRange -> pr, 
 PlotRangePadding -> {Scaled[0.02], Scaled[0.05]}]

Mathematica graphics

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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