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$ Commented 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$ Commented 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$ Commented 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$ Commented 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$ Commented Mar 16, 2013 at 8:10
  • $\begingroup$ Yes I suppose that's the only way... $\endgroup$ Commented Mar 16, 2013 at 8:11
  • $\begingroup$ @cormullion In newer versions there is Texture. $\endgroup$ Commented Mar 16, 2013 at 8:13
  • $\begingroup$ Not on a single face, though apparently $\endgroup$ Commented 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$ Commented 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$ Commented 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$ Commented Mar 18, 2013 at 10:32
  • $\begingroup$ @Mr.Wizard the struggle is clearly visible... :) $\endgroup$ Commented Mar 18, 2013 at 10:43

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.