46

I just saw a nice plot there:

enter image description here

How could I implement that in Mathematica — by which I mean the plot structure, not so much the styling.

F'x
  • 10,817
  • 3
  • 52
  • 92
Mike Honeychurch
  • 37,541
  • 3
  • 85
  • 158
  • 3
    That's not fair, Mike, I have to get a lot of work done today. :) – Verbeia Mar 14 '12 at 21:32
  • 2
    We should both wait for Heike to make something very nice. :) – Mike Honeychurch Mar 14 '12 at 21:34
  • @Verbeia you'll recognize the plot as being from Bloomberg. They also have a plot style for line plots with a gradient fill below the line. Has anyone ever implemented that in Mma? I was thinking of posting that as a question. – Mike Honeychurch Mar 14 '12 at 21:43
  • Look at my answer: yes, I did recognise it as being from Bloomberg :D. I haven't tried to create a gradient Filling before - it's not the sort of thing we do at my employer. We are quite minimalist on the decoration side. – Verbeia Mar 14 '12 at 21:47

4 Answers4

49

There is also a more eye-catchy approach that uses built-in functions.

data = RandomReal[BinormalDistribution[{-1, 2}, {1, 1}, .8], 1000];
GraphicsColumn[
    Table[DensityHistogram[data, {.2}, ColorFunction -> "DarkRainbow",
    Method -> {"DistributionAxes" -> p},
    ImageSize -> 500, BaseStyle -> {FontFamily -> "Helvetica"},
    LabelStyle -> Bold],
    {p, {True, "Histogram", "SmoothHistogram", "BoxWhisker"}}]]

densitiy histograms

And it works also with SmoothDensityHistogram, although it seems that in this case Histogram cannot be used as a method:

GraphicsColumn[
    Table[SmoothDensityHistogram[data, ColorFunction -> "DarkRainbow",
    Method -> {"DistributionAxes" -> p},
    ImageSize -> 500, BaseStyle -> {FontFamily -> "Helvetica"},
    LabelStyle -> Bold],
    {p, {True, "SmoothHistogram", "BoxWhisker"}}]]

enter image description here


Scatterplot with histograms

data = RandomReal[BinormalDistribution[{0, 0}, {1, 1}, .8], 1000];
hist = DensityHistogram[data, {.2}, 
    Method -> {"DistributionAxes" -> "Histogram"}][[1, 2]];
Show[
 Graphics[hist, AspectRatio -> 1, Frame -> True, 
  PlotRangeClipping -> True, 
  PlotRangePadding -> {{Scaled[0.02], Scaled[0.02]}, {Scaled[0.02], 
     Scaled[0.02]}}],
 ListPlot[data]
 ]

enter image description here

VLC
  • 9,818
  • 1
  • 31
  • 60
  • 2
    Where did you learn about all the options for Method -> {"DistributionAxes" ->...} only "BoxWhisker" is listed in the examples. – Mike Honeychurch Mar 30 '12 at 06:18
  • 3
    I stumbled upon an example that used the Histogram as a "DistributionAxes" option, so I followed then the trial-and-error method to find other solutions. It might well be that there are other options out there that work. – VLC Mar 30 '12 at 06:38
  • 15
    Disappointing when users have to guess at these things. they should be documented. – Mike Honeychurch Mar 30 '12 at 07:18
  • @MikeHoneychurch The 'What's New' pages have lots of nice examples. Besides, this is clearly documented, at least as much as experimental features are ever documented. \[MischievousSmiley] – Brett Champion Mar 31 '12 at 19:37
  • 5
    @Brett I think all material relevant to a function should be documented at the function page (novel concept??). That is where people look. i.e. if a user wants information about a function should they go to the function page or scroll through the whats new in version 8 page? Seriously! [ShakngHeadSmiley] – Mike Honeychurch Mar 31 '12 at 21:35
  • 1
    I was just going through Edward Tufte's book - "A Visual Display of Quantitative Information" and saw this (or something very similar to the first "True" example) applied to a scatter plot... Is there no built-in functionality in ListPlot for this? Is the easiest way to overlay the scatter plot on the parts pulled from the histogram? – MRN16 Oct 23 '12 at 20:22
  • @MRN16 I don't think there is a built-in functionality in ListPlot. If you post a question, you might get answers from all users. – VLC Oct 23 '12 at 20:32
  • This is a very nice feature, but I only learned about it here. I have been using DensityHistogram for years, and I had no idea it could do this. @BrettChampion Indeed, it is in the reference page, but very well hidden. May I suggest adding one such example under Basic Examples, at the very beginning? Ot at least under Scope. Just not in Options -> Method. That's the most obscure option, and it's hidden two levels deep within subsections. – Szabolcs Mar 05 '20 at 20:43
  • @VLC is it possible to change the color of the Histogram independently from the color of the 2D plot? – Valerio Jun 02 '20 at 12:48
  • @Valerio Not that I’m aware of. – VLC Jun 02 '20 at 19:03
48

Here's my solution, which constructs the three components and uses Inset to combine them into a single graphic. I've taken some care so that:

  • the coordinate systems should line up across the plots (check the gridlines)
  • as many graphics and plotting options are respected without breaking the layout
  • the graphic can be reasonable resized

customPlot[data_, o___] := 
 Block[{xmin, xmax, ymin, ymax, x, y, mainplot, xhist, yhist, 
   opts = Flatten[{o}]},
  {x, y} = Transpose[data];
  xhist = HistogramList[x, 50];
  yhist = HistogramList[y, 50];
  {xmin, xmax} = Through[{Min, Max}[First[xhist]]];
  {ymin, ymax} = Through[{Min, Max}[First[yhist]]];
  mainplot = 
   ListPlot[data, Frame -> {{False, True}, {False, True}}, 
    Axes -> False, FrameTicks -> None, AspectRatio -> 1, 
    PlotRange -> {{xmin, xmax}, {ymin, ymax}}, 
    PlotRangePadding -> Scaled[0.02], ImagePadding -> {{None, 1}, {None, 1}},
    FilterRules[opts, Options[ListPlot]], 
    FrameStyle -> GrayLevel[0.3], GridLines -> Automatic, 
    GridLinesStyle -> Directive[Gray, Dotted]];
  xhist = 
   Histogram[x, {First[xhist]}, 
    Frame -> {{True, True}, {True, False}},
    FrameTicks -> {{None, None}, {Automatic, None}}, Axes -> False, 
    AspectRatio -> 1/3, ImagePadding -> {{1, 1}, {None, All}},
    FilterRules[opts, Options[Histogram]], 
    GridLines -> {Automatic, None}, FrameStyle -> GrayLevel[0.3], 
    GridLinesStyle -> Directive[Gray, Dotted]];
  yhist = 
   Histogram[y, {First[yhist]}, 
    Frame -> {{True, False}, {True, True}}, Axes -> False, 
    FrameTicks -> {{Automatic, None}, {None, None}}, AspectRatio -> 3,
    BarOrigin -> Left, ImagePadding -> {{All, None}, {1, 1}},
    FilterRules[opts, Options[Histogram]], 
    GridLines -> {None, Automatic}, FrameStyle -> GrayLevel[0.3], 
    GridLinesStyle -> Directive[Gray, Dotted]];
  Graphics[{{Opacity[0], Point[{{360, 360}, {-120, -120}}]},
    Inset[mainplot, {0, 0}, {Left, Bottom}, {360, 360}],
    Inset[xhist, {0, 0}, {Left, Top}, {360, Automatic}],
    Inset[yhist, {0, 0}, {Right, Bottom}, {Automatic, 360}]},
   PlotRange -> {{-120, 360}, {-120, 360}}, 
   FilterRules[opts, Options[Graphics]], 
   ImagePadding -> {{30, 1}, {30, 1}}]
  ]

Now to create some data and try it out:

d = RandomVariate[BinormalDistribution[{0, 0}, {1, 2}, 0.4], 100];

customPlot[d]

enter image description here

customPlot[d, 
   PlotStyle -> Directive[PointSize[Large], Orange], 
   ChartStyle -> Orange, ChartElementFunction -> "FadingRectangle", 
   FrameStyle -> White, Background -> Black]

enter image description here

Brett Champion
  • 20,779
  • 2
  • 64
  • 121
  • nice one Brett. :) – Mike Honeychurch Mar 15 '12 at 00:58
  • 1
    This can occasionally get misaligned due to the placement of the plot markers. Try evaluating it many times and you'll get a random dataset that shows this eventually. Here's an example I got by accident: http://i.stack.imgur.com/M7ulr.png I really really wish it were easier and less painful to robustly align things in Mathematica ... – Szabolcs Mar 15 '12 at 08:33
  • 2
    @Szabolcs I just set ImagePadding on all the components to fix this (which means that tick labels may get clipped slightly.) – Brett Champion Mar 15 '12 at 14:29
  • 1
    @BrettChampion Very pretty ;-) – Vitaliy Kaurov Mar 16 '12 at 06:06
19

This doesn't have the styling and it doesn't yet enforce the plot ranges or implement the regression line, but it's a start:

fakeBloombergThing[data:{{_?NumericQ, _?NumericQ}..}] := 
 Grid[{{Histogram[data[[All, 2]], BarOrigin -> Left , 
     AspectRatio -> 5, ImageSize -> 80], 
    ListPlot[data, Frame -> True, AspectRatio -> 1, 
     ImageSize -> 350]}, {Null, 
    Histogram[data[[All, 1]] , AspectRatio -> 1/5, 
     ImageSize -> 350]}}]

Some fake data:

testdata = 
 RandomVariate[BinormalDistribution[{-1, 1}, {1, 2}, -.6], 100];

fakeBloombergThing[testdata]

enter image description here

Verbeia
  • 34,233
  • 9
  • 109
  • 224
  • I'd probably add some fixed ImagePadding as well for cases where significant figures in ticks can be large. That might also correct the misalignment of the "Y" histogram x axis with the scatter plot x axis. – Mike Honeychurch Mar 14 '12 at 21:58
  • Yes, I hadn't finessed that stuff yet. People should feel free to edit this. – Verbeia Mar 14 '12 at 22:00
19

Here's a truly hacky approach that uses Show to align a ListPlot of the points with the DensityHistogram, which we use only for the histograms along the axes. In order to hide the actual density histogram, we make everything white (which somewhat limits the styling options).

somePoints = RandomReal[BinormalDistribution[{-1, 2}, {1, 1}, .8], 1000];
Show[
 DensityHistogram[somePoints, {.2}, ColorFunction -> (White &),
  Method -> {"DistributionAxes" -> "Histogram"}],
 ListPlot[somePoints]]

the plot

VLC
  • 9,818
  • 1
  • 31
  • 60
Pillsy
  • 18,498
  • 2
  • 46
  • 92
  • 2
    You can have more flexibility using ColorFunction -> (Opacity[0] &) instead of ColorFunction->(White &) – Verbeia Mar 30 '12 at 03:54