5
$\begingroup$

I am trying to plot a matrix with bars, and show what the perfect case would give in the form of non-filled bars. The bars I was able to create:

data = {{0.002, 0, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`}, {0.`, 0.003`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`}, {0.`, 0.`, 0.0023`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`}, {0.`, 0.`, 0.`, 0.001`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`}, {0.`, 0.`,0.`, 0.`, 0.25`, 0.`, 0.`, 0.`, 0.3`, 0.`, 0.`, 0, 0.`, 0.`, 0.`,0, 0.`, 0.`}, {0.`, 0.`, 0.`, 0.`, 0.`, 0.01`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`}, {0.`, 0.`, 0.`, 0.`,0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.20, 0.`, 0.`, 0.`,0.`}, {0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.010, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`}, {0.`, 0.`, 0.`, 0.`, 0.`, 0.`,0.`, 0.`, 0.0021, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`}, {0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.002, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`}, {0.`, 0.`, 0.`, 0.`, 0.`, 0.`,0.`, 0.`, 0.`, 0.`, 0.02, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`}, {0.`, 0.`, 0.`, 0.`, 0.2, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.2,0.`, 0.`, 0.`, 0.1, 0.`, 0.`}, {0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.005, 0.`, 0.`, 0.`, 0.`,  0.`}, {0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`,0.`, 0.001, 0.`, 0.`, 0.`, 0.`}, {0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.0020`, 0.`, 0.`, 0.`}, {0.`, 0.`, 0.`, 0.`, 0, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.2, 0.`, 0.`, 0.`, 0.30, 0.`, 0.`}, {0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.00, 0.`}, {0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`,0.`, 0.`, 0.`, 0.`, 0.`, 0.000}};

data3D = Join @@ MapIndexed[Append[#2, #] &, data, {2}];

col = {0.5, 0.2, 0.5};
bar[n_][{x_, y_, z_}] := {Opacity[1], Hue[((Sqrt[y^2 + x^2])/(3 Length[data])) + .14], Cuboid[{x - n, y - n, 0}, {x + n, y + n, z}]}

image = Graphics3D[bar[0.3] /@ data3D, Axes -> True, Ticks -> {{{1, ""}}, None, {0, .1, .2, .3, {.35, ""}}}, BoxRatios -> {1, 1, .6}, Boxed -> False, FaceGrids -> {{{-1, 0, 0}, {{0.3, 18.7}, {0, .1, .2, .3, .35}}}, {{0, 1, 0}, {{0, 18.7}, {0, .1, .2, .3, .35}}}, {{0, 0, -1}, {{0.3, 18.7}, {0.3, 18.7}}}}]

picture output

What I would like is that the filled bars are overlayed with with unfilled bars. One wonderful example can be seen here.

How can one add these unfilled bars? (In my example, they should all go up to 0.4.).

And optionally: In this plot, there are color codes outside the actual matrix (grey + blue/red/green/violet). How can that be done?

$\endgroup$
  • $\begingroup$ Which bars exactly would you like to have with your styling on, just the outliners? $\endgroup$ – M.R. Oct 14 '15 at 1:24
  • $\begingroup$ I am extremely disappointed to find that Mathematica has included BarChart3D to achieve precisely this sort of outcome, but for some reason, one cannot combine ChartLayout->{"Stacked","Grid"} as one would expect. In the future, I suspect this type of feature will be available and automatic, so that you would simply type BarChart3D[data,ChartLayout->{"Stacked","Grid"}] to produce the chart you desire. $\endgroup$ – Kellen Myers Dec 6 '15 at 18:56
2
$\begingroup$

Adding the unfilled bars can be done with a simple modification to your bars function.

All this does is to draw another cuboid on top of any bar that is taller than some arbitrary cut off (0.1), and include an Opacity[0] to make it unfilled.

(* your current bar function *)

bar[n_][{x_, y_, z_}] := {Opacity[1], Hue[((Sqrt[y^2 + x^2])/(3 Length[data])) + .14], Cuboid[{x - n, y - n, 0}, {x + n, y + n, z}]}

(* my modified bar function *)

bar[n_][{x_, y_, z_}] := {Opacity[1], Hue[((Sqrt[y^2 + x^2])/(3 Length[data])) + .14], Cuboid[{x - n, y - n, 0}, {x + n, y + n, z}], If[z > 0.1, {Opacity[0], Cuboid[{x - n, y - n, z}, {x + n, y + n, 0.4}]}]}

plot with unfilled bars

I didn't write a solution for adding the colour codes outside the matrix, but they could be done by drawing Polygon[...]'s in the right places with the right colours.

$\endgroup$
  • $\begingroup$ Another possibility is afforded by {FaceForm[], Cuboid[(* stuff *)]}. $\endgroup$ – J. M. will be back soon Oct 17 '15 at 2:42
  • $\begingroup$ Ah of course, overlaying two plots. That didn't occure to me. Thank you! Furthermore, why is your graphics so much nicer than mine? $\endgroup$ – NicoDean Oct 17 '15 at 20:06
  • 1
    $\begingroup$ hmm, I exported the plot with a higher resolution than the default: Export["image.png",(*the plot*),ImageResolution->300]. I'm also running version 10. They changed the default plotting styles in V10 so that might account for other differences. $\endgroup$ – rhuairahrighairidh Oct 17 '15 at 21:26
1
$\begingroup$

You can also use BarChart3D with a custom ChartElementFunction and appropriate options to get the same result:

ClearAll[cef]
cef[cedf_: "Cube", opacity_: Opacity[0]] := ({#3[[1]], ChartElementData[cedf][##], 
   If[#[[3, 2]] > .1, {FaceForm[opacity], 
    ChartElementData[cedf][{#[[1]], #[[2]], {#[[3, 2]], .4}}, ##2]}, {}]} &);

Use the color information as metadata:

datameta = MapIndexed[# -> Hue[((Sqrt[#2[[2]]^2 + #2[[1]]^2])/(3 Length[data])) + .14] &, 
  data, {2}];

Use BarChart3D with a "Grid" layout:

BarChart3D[datameta, ChartLayout -> "Grid", 
 Method -> "Canvas" -> False, BarSpacing -> {.1, .1}, 
 FaceGrids -> {{-1, 0, 0}, {0, 1, 0}, {0, 0, -1}}, 
 ChartElementFunction -> cef[]]

enter image description here

Use BarSpacing -> {.5, .5} to get

enter image description here

Use ChartElementFunction -> cef["ProfileCube", Opacity[.2]] to get

enter image description here

$\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.