5
$\begingroup$

Please forgive me if this is a relatively simple thing to do, but I'm relatively new to Mathematica and I've only recently started using it to visualise some statistics for my PhD work (I'm a linguist and this type of coding is like a foreign language to me, but not my kind of foreign language!!).

Is it possible to combine a box plot, histogram and normal distribution curve in one plot (for three datasets, no less)? What I would like to create is something like this: http://support.sas.com/kb/35/171.html (under the 'results' tab) for my three datasets one one plot, with the box plot ideally below the main chart.

I've already managed to create histograms with normal distributions overlaid, but my problem is creating a box plot with the same scale so that it can be positioned directly above/below, or better still, form part of the same plot.

I'll give an example of the three datasets for you to use:

data1 = {33.00,55.74,46.68,22.26,45.05,41.95,82.26,58.79,30.89,30.89,47.21,30.16,17.16,28.05,25.63}
data2 = {34.65,28.52,9.77,38.58,32.03,22.26,35.16,45.26,21.71,29.26,34.71,22.16}
data3 = {23.41,48.54,32.97,28.57,23.35,20.70,35.49,21.97,29.81,17.65,16.73,15.32,16.00}

Any help would be greatly appreciated!

$\endgroup$
10
$\begingroup$

This is very similar to Quantum_Oli's answer, but I will post it anyway. It use's a modified version of Jens's plotGrid function to do the work of combining the plots. The function is imported from a pastebin to save space here,

<< "http://pastebin.com/raw/tmMYLyMh";
hist = Show[
   Plot[140 PDF[SmoothKernelDistribution[#], x] & /@ {data1, data2, 
      data3}, {x, 0, 100},
    Evaluated -> True,
    PlotStyle -> {Red, Green, Blue},
    Frame -> True, PlotRange -> {{0, 100}, All}],
   Histogram[{data1, data2, data3}, ChartStyle -> {Red, Green, Blue}]];
bxchrt = BoxWhiskerChart[{data1, data2, data3}, BarOrigin -> Left, 
   AspectRatio -> 1/3, ChartStyle -> {Red, Green, Blue},
   PlotRange -> {First@Charting`get2DPlotRange@hist, All}, 
   PlotRangePadding -> None];
plotGrid[{{hist}, {bxchrt}}, 500, 400, "KeepAR" -> True]

Mathematica graphics

$\endgroup$
  • $\begingroup$ There are two things that would really make this perfect (1) The 'ticks' on the x-axis on the box plot and histogram do not line up, and (2) To have the histogram not overlaid or stacked, but side-by-side. I've tried doing this as indicated in mathematica.stackexchange.com/questions/15844/… but the scale is all wrong. The histogram is squashed in a small area and no where near the same scale as the rest of the chart. Any thoughts? $\endgroup$ – cwalker Apr 27 '16 at 14:43
  • $\begingroup$ @cwalker - the first I can do, just did. But the second, I don't know how. How about having them like this: i.stack.imgur.com/gS4DS.png , using the function here $\endgroup$ – Jason B. Apr 27 '16 at 15:17
  • $\begingroup$ Ah - clever! I knew there would be a simple solution to it somewhere. As for the second point, that post is beyond me(!!)... I'll keep trying with the method I did as I actually managed to get it to display a chart, and then I might try stealing the 'plot range' code you used above to see if I can adapt that. $\endgroup$ – cwalker Apr 27 '16 at 15:48
  • $\begingroup$ No joy - I'll post it as a new question in a new thread as it's now a bit of a different problem. Thanks for the help anyway - it's already loads more than I could have managed myself! $\endgroup$ – cwalker Apr 27 '16 at 15:53
  • $\begingroup$ One more query: what does the "140" signify/do before the "PDF"? And is there a way to have the y axis labelled with the histogram 'count' rather than the PDF values? (or does it? when I've used this code for other data it seems to show PDF values)... sorry for the seemingly basic questions - I'm a novice when it comes to maths. $\endgroup$ – cwalker Apr 28 '16 at 14:43
8
$\begingroup$

It is indeed possible, although not necessarily straightforward. The method I present below gives a pretty robust and accurate way of lining up plots, the downside is a little bit of code and having to specify a few different options. I'm used to it, it works.

The key is that by specifying the ImageSize, and the Left and Right components of the ImagePadding (along with eliminating PlotRangePadding, then the two plot areas line up horizontally.

We then use Column to trivially position one above the over.

First I declare all the common options and their values:

{xmin, xmax} = {0, 120};
imPadLR = {30, 10};

opts = Sequence[
   PlotRangePadding -> None,
   ImageSize -> 350
];

Then create the histogram and box whisker

hist = Histogram[data1,
   PlotRange -> {{xmin, xmax}, {0, 8}},
   Frame -> True,
   FrameLabel -> {{"Percent", None}, {None, None}},
   ImagePadding -> {imPadLR, {3, 10}},
   opts
];

box = BoxWhiskerChart[data2, "Diamond",
   PlotRange -> {{xmin, xmax}, {0.75, 1.25}},
   BarOrigin -> Left,
   PlotRangePadding -> None,
   FrameLabel -> {{None, None}, {"Horsepower", None}},
   AspectRatio -> 1/10,
   ImagePadding -> {imPadLR, {35, 5}},
   opts
];

And combine with column:

c = Column[{hist, box}]

enter image description here

$\endgroup$
4
$\begingroup$

Perhaps this is helpful or can be adapted. Using the data from OP. Note the "normal distribution" has been scaled for effect (not quantitative):enter image description here

d = {data1, data2, data3};
style = {Red, Green, Blue};
lab = {"data1", "data2", "data3"};
dc = DistributionChart[Join[Table[Null, {3}], d], ChartStyle -> style];
bw = BoxWhiskerChart[d, ChartStyle -> style];
n = EstimatedDistribution[#, NormalDistribution[a, b]] & /@ d;
nd = MapIndexed[
   Table[{6 + #2[[1]] + 10 PDF[#1, j], j}, {j, 0, 100, 1}] &, n];
lp = ListPlot[nd, Joined -> True, PlotStyle -> style];
Show[bw, dc, lp, 
 FrameTicks -> {{Automatic, 
    None}, {Table[{j, lab[[Mod[j, 3, 1]]]}, {j, 1, 9}], None}}, 
 ImageSize -> 400]
$\endgroup$

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.