2
$\begingroup$

The following:

data = Table[i, {i, -10, 10, 0.1}];
ListPlot[data,
   DataRange -> {-10, 10}, Joined -> True, 
   PlotRange -> {{-10, 10}, {-5, 5}}, 
   ColorFunction -> 
    Function[{x, y}, 
     Blend[{{0., Red}, {.5, Blue}, {1., Green}}, x]]]

Produces:

Output of the above code showing the undesired outcome.

But I'd like to be able to apply the ColorFunction like this:

This is the desired outcome.

Which is produced by:

data = Table[i, {i, -5, 5, 0.1}];
ListPlot[data,
 DataRange -> {-5, 5}, Joined -> True, 
 PlotRange -> {{-10, 10}, {-5, 5}}, 
 ColorFunction -> 
  Function[{x, y}, Blend[{{0., Red}, {.5, Blue}, {1., Green}}, x]]]

However, it is necessary that the data and DataRange not be changed, i.e., there should be some way to produce the outcome of the above code by using the initial code which was defined.

Even using Plot:

Plot[x, {x, -10, 10}, PlotRange -> {{-10, 10}, {-5, 5}}, 
 ColorFunction -> 
  Function[{x, y}, Blend[{{0., Red}, {.5, Blue}, {1., Green}}, x]]]

Produces the same undesired outcome as in the first image. The same method for the initially defined code should work for this as well, wherein the ColorFunction is applied to only what is visible within the PlotRange. (Ergo, here it would be such that the {x, -10, 10} needs to remain unchanged.)

How can ColorFunction be applied only to what is visible within the PlotRange?

$\endgroup$
  • $\begingroup$ @C.E. Yes this would be correct to assume. The data range helps prevent ListPlot from just assigning the index as the x-coordinate, and it’s helpful that the user doesn’t need to do some transposition procedure to make the (x, y) pairs themselves (especially for a list of lines, as opposed to just one line as it is here). And the plot range then dictates what is visible of that data that’s been affected by the data range. The setting of the data range is necessary, and I’d think there should be some way to only apply ColorFunction to what is visible in the plot range. $\endgroup$ – CA Trevillian Jul 25 at 11:51
  • 1
    $\begingroup$ If you cannot change the PlotRange or DataRange, rescale the ColorFunction, e,g., ListPlot[data, DataRange -> {-10, 10}, Joined -> True, PlotRange -> {{-10, 10}, {-5, 5}}, ColorFunction -> Function[{x, y}, Blend[{{0., Red}, {.5, Blue}, {1., Green}}, Rescale[x, {-5, 5}]]], ColorFunctionScaling -> False] $\endgroup$ – Bob Hanlon Jul 25 at 11:55
  • $\begingroup$ @BobHanlon that’s a decent idea, but wouldn’t that would only work for this example, though? My visible x-range is (-10, 10), but only by chance is the visible part of the line ranging from (-5, 5). If I have a more complicated set of functions/data, I would have to manually set this for each line. Which, if it comes down to it, this is possible, but not as trivial as I hope it can be. $\endgroup$ – CA Trevillian Jul 25 at 12:06
4
$\begingroup$

If the DataRange and the PlotRange cannot be changed, then at the expense of plotting twice:

$Version

(* "12.1.1 for Mac OS X x86 (64-bit) (June 19, 2020)" *)

Clear["Global`*"]

data = Table[i, {i, -10, 10, 0.1}];

lp = ListPlot[data,
   DataRange -> {-10, 10},
   Joined -> True,
   PlotRange -> {{-10, 10}, {-5, 5}}];

Determine the visible range of x in the plot

{xmin, xmax} = MinMax[Select[
    Cases[lp, {_?NumericQ, _?NumericQ}, Infinity],
    Element[#, Rectangle @@ Transpose[
        PlotRange /. Options[lp, PlotRange]]] &][[All, 1]]]

(* {-5, 5.} *)

Redraw the plot with a ColorFunction scaled to the visible range.

ListPlot[data,
 DataRange -> {-10, 10},
 Joined -> True,
 PlotRange -> {{-10, 10}, {-5, 5}},
 ColorFunction -> Function[{x, y},
   Blend[{{0., Red}, {.5, Blue}, {1., Green}},
    Rescale[x, {xmin, xmax}]]],
 ColorFunctionScaling -> False]

enter image description here

| improve this answer | |
$\endgroup$
  • $\begingroup$ Does this only work for a single line at a time? $\endgroup$ – CA Trevillian Jul 25 at 18:43
  • $\begingroup$ I was able to finagle this to work for what I needed once I changed up the min/max of the visible range to work for a set of lines! I'll wait a bit to accept this in case anyone wants to put anything else down, but I think this worked well for what I needed :D Thanks Bob! $\endgroup$ – CA Trevillian Jul 26 at 1:57
  • $\begingroup$ Hey Bob, can you show how one might do this for Plot? It seems it only works (without some necessary finagling) for ListPlot. When I use the MinMax code it likes to grab up some of the extra parts of the plotting (maybe related to using Frame?) and gives me an inaccurate Min/Max range. Though, the general concept helped me accomplish what I wanted! $\endgroup$ – CA Trevillian Jul 27 at 13:56
  • 1
    $\begingroup$ @CATrevillian - if you are plotting f[x] use {xmin, xmax} = #[{x, pltRng[[1, 1]] <= x <= pltRng[[1, 2]], pltRng[[2, 1]] <= f[x] <= pltRng[[2, 2]]}, x, Reals] & /@ {MinValue, MaxValue}; or, if necessary, replace {MinValue, MaxValue} with {NMinValue, NMaxValue}. $\endgroup$ – Bob Hanlon Jul 27 at 15:16

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.