# PairwiseScatterPlot with histograms along the diagonal

The built-in function PairwiseScatterPlot has been discussed for example here: Scatterplots for subsets of multivariate data [Updated]. However, I find it not very informative to plot the identity function along the diagonal of the matrix of plots: do you guys know how to plot a more informative histogram instead? Also, it is superfluous to plot the entries above the diagonal.

Here is an example:

Needs["StatisticalPlots"]
Needs["MultivariateStatistics"]
data = RandomReal[MultinormalDistribution[{0, 0, 0}, {{1, 1/2, -2/3}, {1/2, 5, 2}, {-2/3, 2, 20}}], 10^3];
PairwiseScatterPlot[data, DataTicks -> Automatic, DataLabels -> {"var1", "var2", "var3"}] UPDATE: I have improved the code a user wrote as a possible solution (unfortunately that user deleted that entry). Basically I have fixed a bug and the labels. Here is what it does:

pspF3 = With[{dt = #, ca = ConstantArray[Null, {#, #} &@Dimensions[#][]],
opts = Sequence[AspectRatio -> 1, Frame -> True]},
GraphicsGrid[ReplacePart[ca, {{i_, i_} :> Histogram[dt[[All, i]], Automatic, "PDF", opts,
If[i == Dimensions[dt][], FrameLabel -> {"var" <> ToString[i], None}, FrameLabel -> None],
PlotRange -> All, Ticks -> Automatic],
{i_, j_} /; i > j :> ListPlot[dt[[All, {j, i}]], opts,
Which[i == Dimensions[dt][] && j > 1, FrameLabel -> {{None, None}, {"var" <> ToString[j], None}}, i == Dimensions[dt][] && j == 1, FrameLabel -> {{"var" <> ToString[i], None}, {"var" <> ToString[j], None}}, i > 1 && j == 1, FrameLabel -> {{"var" <> ToString[i], None}, {None, None}}, i > j, FrameLabel -> {None, None}],
RotateLabel -> True,PlotRange -> All]}], ImageSize -> 600]] &;
pspF3@data However, the ticks are not aligned and the labels of the ticks are repeated when not necessary (they should appear only at the very bottom and on the left). Also, the size of the various frames is not constant and ideally there should not be gaps. PairwiseScatterPlot does all this automatically. Can you improve on this solution?

• One approach is to build your own grid of plots based on GraphicsGrid or Grid. Reproduce the six off-diagonal plots using ListPlot, and use Histogram or whatever else you like for the three diagonal plots. – bbgodfrey Dec 27 '14 at 16:31

Update 3: Using the function pwScatterPlot from this answer

ClearAll[addHistograms, pwScatterPlot]
addHistograms = Module[{diag = Diagonal[Partition[Cases[#, {dir_, ___Point} :> dir, All],
Round @ PlotRange[#][[1, 2]]]]},
# /. {c : Alternatives @@ diag, p__Point} :> Module[{xy = Cases[{p}, Point[x_] :> x]},
Inset[Histogram[xy[[All, 1]], ChartStyle->c, AspectRatio->1/GoldenRatio, Axes -> False],
Min /@ Transpose@xy, {Left, Bottom}, {.9, .9}]]] &;

Needs["StatisticalPlots"]


To use this function on an input data with n series we need to use an n-by-n matrix of styles where the diagonal entries are different from off-diagonal entries.

data2 = RandomReal[MultinormalDistribution[{0, 1, 2},
{{1, 1/2, 1/3}, {1/2, 2, 1/3}, {1/3, 1/3, 3}}], 10^3];
labels2 = "var" <> ToString[#] & /@ {1, 2, 3};
colors2 = {{Red, Blue, Green}, {Blue, Orange, Magenta}, {Green, Magenta, Purple}};

pwScatterPlot[data2, DataSpacing -> .1, DataTicks -> Automatic,
DataLabels -> labels2, ImageSize -> 500, PlotStyle -> colors2] pspF = With[{dt=#,ca=ConstantArray[1,{#,#}&@Dimensions[#][]],
opts=Sequence[Axes->False,AspectRatio->1]},
Grid[ReplacePart[ca, {{i_,i_}:>Histogram[dt[[All,i]],opts],
{i_,j_}:>ListPlot[dt[[All,{i,j}]],opts]}],
Dividers->All]]&;

data1 = RandomReal[MultinormalDistribution[{0, 0}, {{1, 1/2}, {1/2, 1}}], 10^2];
pspF@data1 data2 = RandomReal[MultinormalDistribution[{0, 0,0},
{{1, 1/2,1/3}, {1/2, 2,1/3},{1/3,1/3,3}}], 10^3];

pspF@data2 Update 1: Using DensityHistogram with the option Method -> {"DistributionAxes"->True}:

dhF=With[{dt=#,ca=ConstantArray[1,{#,#}&@Dimensions[#][]],
opts=Sequence[Axes->False,AspectRatio->1]},
Grid[ReplacePart[ca, {{i_,i_}:>Histogram[dt[[All,i]],opts],
{i_,j_}:>DensityHistogram[dt[[All,{i,j}]],opts,
Frame->False,Method->{"DistributionAxes"->True},
ChartElementFunction->"Point"]}],
Dividers->All]]&;

data2 = RandomReal[MultinormalDistribution[{0, 0,0},
{{1, 1/2,1/3}, {1/2, 2,1/3},{1/3,1/3,3}}], 10^3];

dhF@data2 Note: You can also use "BoxWhisker", "Histogram" or "SmoothHistogram" as the setting for the suboption "DistributionAxes".

Update 2: To include PlotLabels, FrameLabels, FrameTicks etc, add these options to Histogram and/or to ListPlot:

pspF2 = With[{dt = #, ca = ConstantArray[1, {#, #} &@Dimensions[#][]],
pr = Through[{Min, Max}[#]], opts = Sequence[AspectRatio -> 1, Frame -> True]},
Grid[ReplacePart[ca,
{{i_, i_} :> Histogram[dt[[All, i]], Automatic, "Count", opts,
PlotRange -> {pr, Automatic},
FrameLabel -> {{"Count", None}, {"var" <> ToString[i], None}},
PlotLabel -> ("var" <> ToString[i])], {i_, j_} :>
ListPlot[dt[[All, {i, j}]], opts, PlotRange -> {pr, pr},
FrameLabel -> {{"var" <> ToString[i], None}, {"var" <> ToString[j], None}},
PlotLabel -> ("var" <> ToString[i] <> "     versus   var" <>
ToString[j])]}], Dividers -> All]] &;

data2 = RandomReal[MultinormalDistribution[{0, 1, 2},
{{1, 1/2, 1/3}, {1/2, 2, 1/3}, {1/3, 1/3, 3}}], 10^3];

pspF2@data2 • thanks! Is it possible to also include DataLabels and DataTicks? – Valerio Dec 28 '14 at 23:09
• @Valerio, please see the update. – kglr Dec 28 '14 at 23:46
• thanks but the labels should appear only on the outer frames and so the numbers associated with the ticks (see my updated plot). Also, if I test pspF2 with data of my example (I've changed the covariance matrix to make obvious which is var1 and which is var2`) I get the wrong ordering, that is the columns do not have the same variables for the various x-axes: to have the right ordering I have to transpose the matrix. – Valerio Dec 29 '14 at 23:40
• @Valerio, just saw your update with a specific example of what you need. I am afraid we need a more elaborate function than pspF to get a full-fledged trellis display like the example in the linked article. Deleting for now until I find a better approach. – kglr Dec 29 '14 at 23:51