I'm assuming you want to change the colors used in an existing plot, not replot it with a different set of colors, correct?
–
rcollyerMay 8 '12 at 3:24

@rcollyer Yeah. Basically, I generate lots of ListDensityPlots from a large dataset, then want to use a different ColorFunction for a select one or two of them.
–
Eli LanseyMay 8 '12 at 4:37

plot is a graphics object, it does not retain information of the underlying mathematical function used to construct it (i.e. you cannot access the "z" values). You can replace the VertexColors in the graphics object, but you'd need to map rgb values between colormaps.
–
kadrachMay 8 '12 at 4:43

3 Answers
3

One solution that works quite well and is fast (interpolation would've been slow), is to use Nearest on a fine grid. The advantage is that you don't have to re-evaluate your plot, or modify it prior to generating it like Yu-Sung's answer does. Here's an example:

That works (+1), but FindMinimum works too and requires no grid.
–
JensMay 8 '12 at 6:27

@Jens Yeah, I thought about FindMinimum, but wasn't sure about how robust it would be for arbitrary and complicated colormaps (I'm not questioning it, just am too sleepy/lazy to think through... )
–
The Toad♦May 8 '12 at 6:34

Agreed, there are bound to be cases where FindMinimum will give a wrong local minimum.
–
JensMay 8 '12 at 6:44

1

One can make this ~30 times faster by setting nr = Nearest[list] before hand, and then doing convert[s_String][x_List] := List @@ ColorData[s][First@nr[x]].
–
Chip HurstFeb 28 '14 at 21:28

So in theory, by replacing VertexColors with other color values, you can change the colors without reevaluation.

Good News

By default, DensityPlot uses color functions on z values and it is scaled (ColorFunctionScaling->True), which makes our task a bit easier since scaled z-values between 0 and 1 will be applied to color functions.

Bad News

We need z-values because we need to apply color functions on them. But, the color function is already evaluated, and only RGB values are stored in VertexColors. Thankfully, the default color function is 1-1 function, but there is no such guarantee in general. Also, the inverse function of the color functions are not trivial (not that hard, just will take some time to compute--beating the purpose of not re-evaluating).

Solution

A bit of cheating. But let's set up the graphics a bit so that it actually contains useful information. Instead of the default color function, let's use GrayLevel.

Usually, the positions in plot outputs are pretty stable unless you change options that modifies geometry (such as Exclusions), and there is a slight worry that Position may cause unpacking of nicely packed plot outputs (read this), so let's stick to this value for a while (of course, actual replace should be {1, 3, 2}, the second argument of the rule). A simple test:

Problems

If the goal is to completely avoid Kernel evaluation, there is no easy solution--if not impossible, since ColorData will rely on the Kernel evaluation anyway.

Calling ColorData (and any other color functions, such as Blend or Hue for that matter) manually like this is not efficient in two ways;

First, internal plot functions do a lot of optimization for calling color data. Essentially it is getting a treatment like CompliedFunction, but more specialized. By manually calling them, you are not getting much speed up.

Secondly, the output form is a list of RGBColor[...] which makes the whole result unpacked. Not efficient memory-wise.

There is a way to achieve maximum efficiency by turning ColorData into a linear interpolation function of triples and using CompiledFunction or InterpolatingFunction, but I frankly don't think that it is worth...

So in principle, this works. However, Hue is special because it is invertible easily. For the default color scheme ("LakeColors") that's not so easy. InverseFunction seems to be unavailable for the blends appearing there.

So one would have to do the inversion by hand, probably using FindMinimum, applied to the difference between RGBColors in the VertexColors list and the RGBColors returned by the original color function. It's a FindMinimum problem because numerically the inversion may not work.

Edit

What I did with the Hue example was cheating in the same way that Yu-Sung Chang's solution based on GrayLevel was cheating, because the default color functions are more complicated. So here is something that works for the blends in the ColorData list, including the default LakeColors:

Mathematica is a registered trademark of Wolfram Research, Inc. While the mark is used herein with the limited permission of Wolfram Research, Stack Exchange and this site disclaim all affiliation therewith.