# n-dimensional plot

I want to plot 6-dimensional data using parallel axes (https://en.wikipedia.org/wiki/Parallel_coordinates). The list looks like this:

    {{a1,b1,c1,d1,e1,f[a1,b1,c1,d1,e1]},{a2,b2,c2,d2,e2,f[a2,b2,c2,d2,e2]},{},...}


I need to draw six vertical axes with scales on them, connect the dots with lines, and color these lines according to the value of f[ai,bi,ci,di,ei], or the last coordinate.

A three dimensional example with two data would help me start, but I don't know how to do it.

Thank you.

Here's a start:

parallelPlot[dat_] :=
ListPlot[dat,
Prolog ->
Table[Line[{{i, Min[dat]}, {i, Max[dat]}}], {i,
Length[dat[]]}],
PlotStyle ->
Table[Blend[{Red, Blue},
Rescale[dat[[i, -1]], {Min[dat[[All, -1]]], Max[dat[[All, -1]]]}
]], {i, Length[dat]}],
Joined -> True,
Axes -> False
]


Test:

parallelPlot[RandomInteger[{-5, 5}, {10, 6}]] Things that one can easily add but I don't have time now:

1. Rescale each coordinate separately.
2. Ticks, labels, etc.
3. Colorbar

======= Better function, that also rescales ========

The Rescale function is what you should use for rescaling. Let's keep the minimum and maximum of each dimensions in the variables mins and maxs, and thus

{mins, maxs} = Transpose[{Min[#], Max[#]} & /@ Transpose[data]];
rescaledData =
Transpose@
Table[Rescale[data[[All, i]], {mins[[i]], maxs[[i]]}], {i, Length@data[]}];


We can then use mins and maxs to create tick labels at the bottom and top of each dimension. Here's the integrated code (I also added a Floor and Ceiling functions in the calculation of mins and maxs to make the bounds nicer):

parallelPlot[data_] := Block[{mins, maxs, rescaledData, n, ndim},
n = Length[data];
ndim = Length[data // First];
{mins, maxs} = Transpose[{Floor@Min[#], Ceiling@Max[#]} & /@ Transpose[data]];
rescaledData =
Transpose@
Table[Rescale[data[[All, i]], {mins[[i]], maxs[[i]]}], {i, ndim}];
ListPlot[rescaledData,
Prolog -> Table[Line[{{i, 0}, {i, 1}}], {i, ndim}],
PlotStyle -> Table[Blend[{Red, Blue}, rescaledData[[i, -1]]], {i, n}],
Epilog -> {
Table[Text[mins[[i]] // ToString, {i, 0}, {-1, 0}], {i, ndim}],
Table[Text[maxs[[i]] // ToString, {i, 1}, {-1, 0}], {i,ndim}]
},
Joined -> True,
Axes -> False];


To test, we generate 6-dimensional random data (here its 15 points), where each coordinate is randomly distributed between two random bounds.

d = Transpose@Table[
RandomReal[{Min@#, Max@#} &@RandomInteger[{0, 10}, 2], 15],
{6}]
parallelPlot@d • Like your avatar :) Aug 31, 2015 at 9:00
• Aug 31, 2015 at 9:53
• @Silvia thx. Yours ain't bad neither :) Aug 31, 2015 at 9:55
• Now that you've accepted my answer, I don't have any incentive to do so... Just kidding, I will add it later, maybe tonight. Aug 31, 2015 at 10:20
• @user27670 I added the rescaling code. Aug 31, 2015 at 11:57

I took another stab at the problem to produce a self-contained function that generates axes as well as rescales the data. The function nplot is defined below. It takes a list of data as input

Clear[nplot]

nplot[data_?(ArrayQ[#, 2, NumericQ] &), ImageSize -> size_] := Module[
{rescaled, plot, axes},
rescaled = Transpose@(Rescale /@ Transpose@data);
plot =
ListLinePlot[
rescaled, PlotRange -> {{1, Last@Dimensions@data}, Automatic},
ImageSize -> size, PlotRangePadding -> None, Axes -> None
];
axes =
Map[
ListPlot[
data[[All, #]], PlotStyle -> None,
PlotRange -> {{1, Last@Dimensions@data}, Automatic},
Axes -> {False, True}, PlotRangePadding -> None,
ImageSize -> size, Background -> None,
AxesOrigin -> {#, Automatic}] &,
Range[Last@Dimensions@data]
];
Overlay[Flatten@{plot, axes}]
]

nplot[data_] := nplot[data, ImageSize -> Automatic]


Within nplot I generate a column-wise rescaled version of the data that is plotted using ListLinePlot; the axes of this plot are suppressed, because they will be replaced by more appropriate ones reflecting the non-rescaled value of the variables. I then use the existing ListPlot machinery to generate appropriately scaled and placed axes for the non-rescaled data, which are stored in axes within nplot. Finally, the rescaled plot and non-rescaled axes are overlaid and returned.

The function checks the nature of the input data (it must be at least a 2-dimensional array: a vector would result in a straight line across the plot and would be very uninteresting) and passes through values of the ImageSize option, if set by the user (otherwise a value of Automatic is used).

Here is what the function produces with some random input:

SeedRandom
pts = RandomReal[{-10, 10}, {15, 6}];
nplot[pts, ImageSize -> Large] • Nice. I thought about using Overlay, but the problem is that this produces an object which is not a Graphics, and thus is not amenable to further manipulations. But if this is not an issue then that's probably a simpler approach. Aug 31, 2015 at 16:15
• @yohbs That's very true. I have been trying to get around that limitation, but for now I'm still stuck with Overlay in order to harness a plotting function to auto-generate the axes. I have been looking around for pre-made functions that generate axes, or for access to the built-in ones, but no joy so far. Aug 31, 2015 at 18:28
• I opened a thread to see if someone solved it. You're welcome to join. Sep 15, 2015 at 20:44