5
$\begingroup$

I would like to get a 3D visualization of a given matrix.

Here is a figure which may come from Mathematica. I want to plot something like it. When I use ListPlot3D or BarChart3D to plot my matrix, it does not have the style of one shown below, which is what I'm look for. How can I do a nice 3D visualization of my matrix?

visualization of a matrix

data = ( {
    {1, 2, 3},
    {5, 4, 8},
    {2, 5, 7}
   } );

data = ArrayPad[data, {0, 1}];
xTicks = {{1.5, "A"}, {2.5, "B"}, {3.5, "C"}};
yTicks = {{1.5, "X"}, {2.5, "Y"}, {3.5, "Z"}};
zTicks = {{0, "0"}, 0, {4, "4"}, {8, "8"}};

pic = ListPlot3D[data, 
  Mesh -> None, 
  InterpolationOrder -> 0, 
  ColorFunction -> "Rainbow",
  Filling -> Bottom,
  FillingStyle -> {Opacity[0.9]},
  PlotRange -> {Min[data] - 0.5, Max[data] + 0.2},
  BoxRatios -> {1, 1, 0.5},
  Ticks -> {xTicks, yTicks, zTicks},
  DataRange -> All,
  Boxed -> False,
  FaceGrids -> {Bottom, Back, Left},
  ImageSize -> 400]

this is the code that I plot a matrix using ListPlot3D. The cuboids in it are not separate from each other, and the edges of the cuboid are fuzzy.

my figure for matrix from the above code

$\endgroup$
3
  • $\begingroup$ What code did you try, and in what way does the output "not look good?" $\endgroup$
    – Mr.Wizard
    Mar 16, 2013 at 7:05
  • $\begingroup$ Thanks for adding the code. Now, what don't you like about it? Are you trying to reproduce the first as closely as possible, or is it more general? Do you dislike the text, or the lack of the full box frame around the plot? Put another way: define "nice." $\endgroup$
    – Mr.Wizard
    Mar 16, 2013 at 7:22
  • $\begingroup$ Great thanks Wizard. I want to reproduce the first figure and do some improvement to it, such as the x&y ticks in the original figure do not in the middle of the bottom of the cuboid. $\endgroup$
    – cmc
    Mar 16, 2013 at 7:30

3 Answers 3

11
$\begingroup$

If I have time later tonight I'll give you a graphic matching demo as I did for other users here and here.

As usual I recommend building a specific graphic from Graphics (or Graphics3D) primitives so I suggest you spend some time reading about those, e.g. Cuboid.

As a quick fix you can use BarChart3D as follows:

data = SparseArray[Tuples[{1, 4}, 2] -> 0.3, {4, 4}, 0.01];

chart = BarChart3D[data, ChartLayout -> "Grid"]

Mathematica graphics

There are many Options you can use to customize this. Please spend some time reading about those as well. Once you get comfortable with graphics primitives and the internal format of these objects you can perform manipulations on the output to further customize them.


Okay, here is a fairly close approximation:

data = SparseArray[Tuples[{1, 4}, 2] -> 0.3, {4, 4}, 0.01];
data[[2 ;; 3, 2 ;; 3]] += 0.1;
data3D = Join @@ MapIndexed[Append[#2, #] &, data, {2}];

labels = {"VV", "VH", "HV", "HH"};

bar[n_][{x_, y_, z_}] := Cuboid[{x - n, y - n, 0}, {x + n, y + n, z}]
Graphics3D[
 bar[0.25] /@ data3D,
 Axes -> True,
 LabelStyle -> {FontFamily -> "Helvetica", 19},
 Ticks -> {MapIndexed[{5 - #2[[1]], #} &, labels],
           MapIndexed[{#2[[1]], #} &, labels], 
           Automatic},
 FaceGrids -> {{-1, 0, 0}, {0, 1, 0}, {0, 0, -1}},
 BoxRatios -> {1, 1, 1},
 BoxStyle -> AbsoluteThickness[2.5],
 PlotRangePadding -> 0.25,
 ViewPoint -> 1.5 {1.77, -2.29, 1.74},
 ImageSize -> 330
]

Mathematica graphics

The original:

original

$\endgroup$
5
  • $\begingroup$ +1 but how do you make a cuboid have a red top and blue sides? $\endgroup$
    – cormullion
    Mar 16, 2013 at 8:08
  • $\begingroup$ @cormullion By changing the Lighting. For example the default colors match the OP's image: Graphics3D[Cuboid[]] or in all white: Graphics3D[Cuboid[], Lighting -> "Neutral"] $\endgroup$
    – Mr.Wizard
    Mar 16, 2013 at 8:10
  • $\begingroup$ Yes I suppose that's the only way... $\endgroup$
    – cormullion
    Mar 16, 2013 at 8:11
  • $\begingroup$ @cormullion In newer versions there is Texture. $\endgroup$
    – Mr.Wizard
    Mar 16, 2013 at 8:13
  • $\begingroup$ Not on a single face, though apparently $\endgroup$
    – cormullion
    Mar 16, 2013 at 8:17
4
$\begingroup$
 data = ({{1, 2, 3}, {5, 4, 8}, {2, 5, 7}});
 data = ArrayPad[data, {0, 1}];
 xTicks = {{1, "A"}, {2, "B"}, {3, "C"}};
 yTicks = {{1, "X"}, {2, "Y"}, {3, "Z"}};
 zTicks = {{0, "0"}, 0, {4, "4"}, {8, "8"}};
 pltstyl = {ColorFunction -> "Rainbow", 
  PlotRange -> {Min[data] - .2, Max[data] + 0.2}, 
   BoxRatios -> {1, 1, 0.5}, Ticks -> {xTicks, yTicks, zTicks}, 
   Boxed -> False, FaceGrids -> {Bottom, Back, Left},  ImageSize -> 400};

Using BubbleChart3D with a custom ChartElementFunction:

(* transform data to a form acceptabele to BubbleChart3D:*)
bcdata =Join@@MapIndexed[Composition[Append[#, 1] &, Flatten, Reverse, List], data, {2}]; 
(* custom ChartElementFunction to produce cuboids with appropriate heights *)
ceFunc[{{xmin_, xmax_}, {ymin_, ymax_}, {zmin_, zmax_}}, v_, meta_] :=
  {Cuboid[{xmin, ymin, 0.}, {xmax, ymax, (zmax + zmin)/2}]};
BubbleChart3D[bcdata, ColorFunction -> (ColorData["Rainbow"][#3] &), 
 ChartStyle -> Opacity[.9],
 ChartElementFunction -> ceFunc, BubbleSizes -> {0.15, .15}, 
 Evaluate@pltstyl]

enter image description here

Post-processing BubbleChart3D to reshape the cuboids

BubbleChart3D[bcdata, ColorFunction -> (ColorData["Rainbow"][#3] &), 
 ChartStyle -> Opacity[.9], ChartElementFunction -> "Cube", BubbleSizes -> {0.15, .15}, 
 Evaluate@pltstyl] /. 
CuboidBox[{a_, b_, c_}, {e_, f_, g_},rest___]:>CuboidBox[{a, b, 0}, {e, f,(c + g)/2}, rest]

enter image description here

Using DiscretePlot3D with Interpolation:

(* interpolation of 3D data: *)
intF = Interpolation[Join @@ MapIndexed[Composition[Reverse, List], data, {2}]];
DiscretePlot3D[intF[i, j], {i, 1, 4}, {j, 1, 4}, 
ExtentSize -> Scaled[.75], Evaluate@pltstyl]

enter image description here

$\endgroup$
2
  • $\begingroup$ How to avoid the shift (empty space) between the cubes and the A B C axis? $\endgroup$
    – Thapanio
    Sep 8, 2021 at 7:53
  • $\begingroup$ @Thapanio, try removing the option PlotRange from the definition of pltstyl (or change it to PlotRange -> All). $\endgroup$
    – kglr
    Sep 8, 2021 at 9:15
2
$\begingroup$

I tried to follow in the steps of the great Mr.Wizard, using cuboids, or rather polygons:

cuboid[origin_, box_List, colors_List] := 
 Module[
  {vertexList = {
     {{1, 1, 1}, {0, 1, 1}, {0, 0, 1}, {1, 0, 1}}, (* up *)
     {{1, 1, 1}, {1, 0, 1}, {1, 0, 0}, {1, 1, 0}}, (* right *)
     {{0, 1, 1}, {0, 1, 0}, {0, 0, 0}, {0, 0, 1}}, (* left *)
     {{0, 0, 1}, {0, 0, 0}, {1, 0, 0}, {1, 0, 1}}, (* front *) 
     {{1, 1, 1}, {1, 1, 0}, {0, 1, 0}, {0, 1, 1}}, (* back *)
     {{0, 0, 0}, {0, 1, 0}, {1, 1, 0}, {1, 0, 0}}} (* down *) 
   },
   (* scale *)
   vertexList = Map[Times[box, #] &, vertexList, {2}];
   (* move *)
   vertexList = Map[Plus[origin, #] &, vertexList, {2}];
   Riffle[colors, Polygon /@  vertexList]] 

Then, with some suitable data:

fullData = {{1, 1, 1}, {1, 2, 2}, {1, 3, 3}, {2, 1, 4}, 
    {2, 2, 5}, {2, 3, 6}, {3, 1, 7}, {3, 2, 8}, {3, 3, 9}};
xTicks = {{1.5, "A"}, {2.5, "B"}, {3.5, "C"}};
yTicks = {{1.5, "X"}, {2.5, "Y"}, {3.5, "Z"}};
zTicks = {{0, "0"}, 0, {4, "4"}, {8, "8"}};

Graphics3D[
 {
  cuboid[{#[[1]], #[[2]], 0}, {.5, .5, #[[3]]}, 
    {Cyan, Orange, LightGray, Purple, Gray, Gray}] & /@ fullData
  }, 
 Boxed -> True, 
 Axes -> True, 
 AxesLabel -> {x, y, z}, 
 Lighting -> {{"Ambient", White}},
 FaceGridsStyle -> Directive[Opacity[0.4], Gray],
 PlotRange -> {-2, 10},
 BoxRatios -> {1, 1, 0.7},
 Ticks -> {xTicks, yTicks, zTicks},
 FaceGrids -> {Bottom, Back, Left}

Each face has its own color.

graphic

With this sort of graphic, it's quite hard to read the heights accurately. But that's another story.

$\endgroup$
2
  • $\begingroup$ That was a bit of work! +1 $\endgroup$
    – Mr.Wizard
    Mar 18, 2013 at 10:32
  • $\begingroup$ @Mr.Wizard the struggle is clearly visible... :) $\endgroup$
    – cormullion
    Mar 18, 2013 at 10:43

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.