# SmoothHistogram3D with a ColorFunction representing z-values of the data set

I'd like to make a 3d plot of a list of {x, y, z} points, where the height of the plot scales with the density (as in histogram) of the xy-values and the color scales with the z values.

I think the following is close but the colors don't appear to scale with the z values. I think i'm either not using ColorFunction properly, or I'm not scaling the ColorData values properly (or both, or maybe something completely different!).

I found a few related questions, but none quite the same as this one. An important difference is that I interpolate the data to get the colour function because the z-values in my actual data set are noisy.

Is there a simple fix?

data = RandomReal[1, {100, 3}];
f = Interpolation[data]/Max[data[[;; , 3]]];
SmoothHistogram3D[data[[;; , 1 ;; 2]],
ColorFunction -> Function[{x, y, z}, ColorData["FallColors"][f[x, y]]]]


Following on from the excellent solution by @m_goldberg , I tried adding a BarLegend, using a second function to get the colors to match the raw data rather than data normalized to 1. I first fixed the z range to two values: 0.1 or 0.2 (which for this example simply depends on whether the x value is > or < 0.5) to make it clear if the legend was working. The BarLegend numbers scale to the raw data values as intended, but the colors in BarLegend do not (I get just a very narrow colour band or maybe just one colour?):

SeedRandom;
data = RandomReal[1, {100, 3}];
lt05 = Flatten@Position[data[[;; , 1]], _?(# < 0.5 &)];
data[[;; , 3]] = 0.1;
data[[lt05, 3]] = 0.2;
Clear@f
f[x_, y_] = Quiet@Interpolation[data][x, y]/Max[data[[All, 3]]];
f2[x_, y_] = Quiet@Interpolation[data][x, y]; Quiet@
SmoothHistogram3D[data[[All, ;; 2]],
ColorFunction ->
Function[{x, y, z}, ColorData["SolarColors"][f[x, y]]],
ColorFunctionScaling -> False,
PlotLegends ->
BarLegend[{Function[{x, y, z},
ColorData["SolarColors"][f2[x, y]]], {Min[data[[;; , 3]]],
Max[data[[;; , 3]]]}}]]


How do I make the BarLegend numbers match the raw data range? Using f2 as the argument to ColorFunction, rather than f, results in one colour throughout the plot (with or without ColorFunctionScaling->True).

• why not ColorFunction -> "FallColors"? – Mike Honeychurch Dec 24 '15 at 4:08
• Thanks Mike, the colour should scale with the z values of the original 3d {x,y,z} data. The histogram is only using the {x,y} values, so histogram height represents the density of the x,y points ignoring the z values. I want the colour to vary with the interpolated z values rather than the height of the histogram. f is supposed to be a function giving colour "z" as a function of x and y, whilst the histogram height shows the density of the points in x and y. The z values aren't necessarily greatest where the x y points are densest. (I hope that is a bit clearer, sorry!) – DrBubbles Dec 24 '15 at 6:13

Some reproducible data.

SeedRandom;
data = RandomReal[1, {100, 3}];


Your problem is with the way in which you define f. As you define it

f = Interpolation[data]/Max[data[[All, 3]]];


This f is not a function and does not act like one.

f @@ data[[1, ;; 2]] However, if f is redefined with

Clear @ f
f[x_, y_] = Interpolation[data][x, y]/Max[data[[All, 3]]];


it is a function and behaves well

f @@ data[[1, ;; 2]]


0.350213

Using this 2nd definition of f, the smooth 3D histogram looks like

Quiet @
SmoothHistogram3D[data[[All , ;; 2]],
ColorFunction -> Function[{x, y, z}, ColorData["FallColors"][f[x, y]]]] • Thanks @m_goldberg this works. I need to read up on the meaning of how [...] can follow [...] in the definition of f. – DrBubbles Dec 24 '15 at 8:23