# Manipulating elements of a matrix, to loop or not ?

I have a grid of values generated from a MATLAB evaluation. Most of these elements are 0, some 0.5 and the remainder 1. I'd like to write a mathematica script which reads in the CSV and then, in every position where there is a 1, I'd like it to create a Graphics3D red sphere of radius 1, and in every position where there is an 0.5, a green sphere of radius 1. However, I'm not sure whether the best approach is to use loops or something more natural in Mathematica. To illustrate, here's a sample 5 x 5 matrix;

M = {{0, 0, 0, 0, 0.5}, {1, 0, 0, 0, .5}, {0, 0, 0, 0, 0.5}, {1, 0,
1, 0, 0}, {0, 0, 0, 0, 1}};


I can get all the ones and halfs from the grid as follows;

Ones = Position[M, 1];
Halfs = Position[M, 0.5];
OneLength = Length[Ones];
HalfLength = Length[Halfs];
Xpos = Part[Part[Ones, 1], 1];
Ypos = Part[Part[Ones, 1], 2];


Where I get the lengths in case I need to run a loop - which I'm trying to avoid. Similarly the Xpos and Ypos give a co-ordinate I could loop but I'm sure there's an easier way. In essence, I want to end up with a picture like this for the sample data above;

In the example above, I generated it manually using

j1 = Graphics3D[{Opacity[0.5], Green, Sphere[{5, 6 - 1, 0}]}];
j2 = Graphics3D[{Opacity[0.5], Green, Sphere[{5, 6 - 2, 0}]}];
j3 = Graphics3D[{Opacity[0.5], Green, Sphere[{5, 6 - 3, 0}]}];
j4 = Graphics3D[{Opacity[0.5], Green, Sphere[{4, 6 - 5, 0}]}];
g1 = Graphics3D[{Opacity[0.5], Red, Sphere[{1, 6 - 2, 0}]}];
g2 = Graphics3D[{Opacity[0.5], Red, Sphere[{1, 6 - 4, 0}]}];
g3 = Graphics3D[{Opacity[0.5], Red, Sphere[{3, 6 - 4, 0}]}];
g4 = Graphics3D[{Opacity[0.5], Red, Sphere[{5, 6 - 5, 0}]}];
Show[j1, j2, j3, j4, g1, g2, g3, g4]


Notice that I've subtracted the y element from 6, as Matlab starts its y-count from the top down rather than from the axis, so any matrix I get in from Matlab will need something like this to Y-flip. Is there a clever way to automate this, using table or otherwise which will circumvent loops? If loops are required, what is the most efficient way of creating one? I will eventually be working with 200 x 200 arrays so manual manipulation would be best avoided! Thanks in advance...

• Your manual version has eight spheres, while the matrix only has seven non-null entries. ;) – Jinxed Mar 11 '15 at 12:26

Using Map, you can avoid looping:

Graphics3D[{Opacity[0.5],
{Red, Sphere /@ (Position[M, 1] /. {x_, y_} :> {x, 6 - y, 0})},
{Green, Sphere /@ (Position[M, .5] /. {x_, y_} :> {x, 6 - y, 0})}}]


or a little shorter (but more nerdy):

Graphics3D[{Opacity[0.5],
{#1,Sphere/@#2}&@@{#[[2]],Position[M,#[[1]]]/.{x_,y_}:>{x,6-y,0}}&/@{{1,Red},{0.5,Green}}}]


With some more options, you get your desired 3D-view:

Graphics3D[{Opacity[0.5],
{#1,Sphere/@#2}&@@{#[[2]],Position[M,#[[1]]]/.{x_,y_}:>{x,6-y,0}}&/@{{1,Red},{0.5,Green}}},
ViewPoint->Above,ViewVertical->{0,0,1},Boxed->False,AxesOrigin->{0,0,0},
Axes->{True,True,False},AxesLabel->{"x","y","z"}]


• Brilliant - cheers! – DRG Mar 11 '15 at 18:42
• @DRG: Glad to hear to have been of some help! – Jinxed Mar 11 '15 at 20:40

The MapIndexed function works very nicely for this, as it provides both the value of the array element, and a list representing its position. I wasn't golfing here, so I used pattern matching on function arguments for the rest:

draw[0, _] = {};
draw[v : Except[0], {x_, y_}] :=
{v /. {0.5 -> Green, 1 -> Red},
Sphere[{x, 6 - y, 0}]};

Graphics3D[{
Opacity[0.5],
MapIndexed[draw, M, {2}]}]

• +1. MapIndexed seems the most appropriate tool. I might use Condition with numeric tests, esp. since the data is coming from outside Mathematica. E.g. draw[zero_, _] /; zero == 0 :=... and v /. {v0_ /; v == 0.5 -> Green, v0_ /; v == 1 -> Red}. (For instance 1 matches only the Integer and not the Real number 1, and the numbers might be off by machine epsilon or so. Using Equal allows for such differences.) – Michael E2 Mar 11 '15 at 13:29
• Great answer, will use this technique for something else I have in mind! Thanks – DRG Mar 11 '15 at 18:42