Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have a list of coordinates in form {{x1,y1},{x2,y2},...}

Is there a way in mma to builds density plots based on position ( ListDensityPlot calculates density based on value in {x,y,value})? I want to create something similar to heatmap.py.

share|improve this question
add comment

3 Answers 3

up vote 17 down vote accepted

There are two functions that can do this:

These functions also come in a smoothed version (prepend Smooth to the name), which can be used to obtain results similar to what Heike plotted.

Edit

If you work in a regime where individual points are resolved, you may notice a disconcerting shift in the output of SmoothDensityHistogram (at least I see it on Mac OS X, MMA version 8.0.4):

data = RandomReal[1, {100, 2}];
Show[
 SmoothDensityHistogram[data, 0.015, "PDF",
  ColorFunction -> "Rainbow",
  Mesh -> 0,
  PlotRange -> {{0, 1}, {0, 1}}],
 Graphics[Point@data],
 PlotRange -> {{0, 1}, {0, 1}}
 ]

ShiftedDensity

I only noticed this after looking at R.M.'s plot with the original points superimposed, as shown above.

To fix this and at the same time understand better what these smoothed histogram plots really do, you could take a look at the following function:

heatMap[data_, opts : OptionsPattern[]] := Module[
  {n, size, xRange, pr},
  n = "Points" /. {opts} /. {"Points" -> 100};
  pr = PlotRange /. {opts} /. {PlotRange :> 
      Map[{Min[#], Max[#]} &, Transpose[data]]};
  xRange = -Subtract @@ pr[[1]];
  size = Floor[
    n ("Radius" /. {opts} /. {"Radius" -> xRange/6})/xRange];
  Graphics[{
    Inset[
     ArrayPlot[
      Rescale@GaussianFilter[
        ImageData@ColorNegate@ColorConvert[
           Rasterize[Graphics[Point[data],
             Background -> White,
             PlotRangePadding -> 0,
             ImagePadding -> 0,
             ImageMargins -> 0,
             PlotRange -> pr],
            "Image", ImageSize -> n], "GrayScale"],
        {3 size, size}, Padding -> 0],
      ColorFunction ->  
       (ColorFunction /. {opts} /. 
        {ColorFunction -> 
         ColorData["LakeColors"]
        }
       ),
      ImagePadding -> 0,
      PlotRangePadding -> 0, Frame -> False],
     pr[[All, 1]], {0, 0}, xRange]},
   PlotRange -> pr, Frame -> True, PlotRangePadding -> Scaled[.02]
   ]
  ]

Show[heatMap[data, "Points" -> 300, "Radius" -> .02, 
  PlotRange -> {{0, 1}, {0, 1}}, 
  ColorFunction -> ColorData["Rainbow"]],
 Graphics[Point@data], 
 PlotRange -> {{0, 1}, {0, 1}}]

noSHift

So I basically re-implemented this plotting function by using GaussianFilter, without trying to implement all the options provided by the built-in function.

The options it recognizes are "Points" (the number of sampling points in the horizontal direction), "Radius" (the radius of the Gaussian) and PlotRange.

Besides giving better alignment between the heat map and the points, this manual approach also could be used to do some non-standard things. For example, you could change Padding -> 0 to Padding -> "Periodic" if the data points live on a torus topology.

To show the dependence on the choice of radius, here is a movie:

Export["l.gif", 
 Join[#, Reverse[#]] &@
  Table[Show[
    heatMap[data, "Points" -> 300, "Radius" -> r^2, 
     PlotRange -> {{0, 1}, {0, 1}}], Graphics[Point@data], 
    PlotRange -> {{0, 1}, {0, 1}}],
   {r, .15, .25, .015}], "DisplayDurations" -> .1]

snoothing

Edit

I forgot to add ColorFunction as an option - that's now done, with "LakeColors" as the default, as it is for SmoothDensityHistogram. There was also a Frame -> False missing in ArrayPlot, which I fixed in the code.

As an added bonus, plots created with heatMap take much less space when exported as PDF.

share|improve this answer
add comment

You can use SmoothDensityHistogram to generate heatmaps. This does the same as what Heike's method does, but in one line. Example:

data = RandomReal[1, {100, 2}];
SmoothDensityHistogram[data, 0.02, "PDF", ColorFunction -> "Rainbow", Mesh -> 0]

enter image description here

share|improve this answer
1  
@R.M. Do you also see an offset between the maxima and the original points if you plot them together? I see that on my machine, see my answer. It seems to indicate that someone was sloppy when writing this function. –  Jens May 27 '12 at 23:04
1  
@Jens Yes, it shows up on mine and Heike's too. Looks like SmoothKernelDistribution is the culprit (since SDH calls SKD internally). I did notice a spurious offset in a more involved example I was working on that included image processing, but I didn't realize it was due to SKD and instead thought it was due to some sloppy Dilations on my part... Thanks for pointing this out. Probably should send an email to support@wolfram too... –  rm -rf May 27 '12 at 23:48
3  
I've sent a bug report about SmoothDensityHistogram to Wolfram [TS 21354]. –  Jens May 28 '12 at 5:41
2  
@Jens This is a case where boosting InterpolationPoints to say 256 will be useful. It is more of a failure of automation than a bug. KernelMixtureDistribution might be a better alternative though. –  Andy Ross May 29 '12 at 20:46
1  
@AlexeyPopkov I believe it actually does have this option it just isn't documented. It certainly seems to have an effect for me. –  Andy Ross Sep 15 '12 at 15:43
show 4 more comments

It looks like SmoothKernelDistribution might do the trick. For example

data = RandomReal[1, {100, 2}];

dist = SmoothKernelDistribution[data, .02]

DensityPlot[Evaluate[PDF[dist, {x, y}]], {x, 0, 1}, {y, 0, 1}, 
 PlotRange -> All, ColorFunction -> "SunsetColors", PlotPoints -> 40]

Mathematica graphics

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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