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

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

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

PlotRangePadding
as well. $\endgroup$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$x
, or a lower bound, that you will encounter in your data sets, you could use that inPlotRange
instead of1
or0
. The number0
corresponds to-Infinity
on theLog2
scale, which cannot be plotted. $\endgroup$