# flattening only part of a matrix, manipulating and retrieving the unflattened matrix

I start with a square matrix with odd size. I keep the original version of this matrix. Now, I extract the non-zero elements from the matrix, which lie everywhere except the $3\times3$ block in the center of the matrix, flatten them out and do some manipulations. These manipulations required me to remove the zero elements. Now I want to unflatten these elements into their original positions in the matrix and retrieve the matrix as a whole. I tried assigning labels to each of the elements but that becomes cumbersome. (I am working with a multidimensional array; the matrix here is just for example). How can I do this easily?

• Use SparseArray and ArrayRules. – Anton Antonov Apr 20 '18 at 15:34
• matrix={{a,b,c,d},{e,f,g,h},{i,j,k,l},{m,n,o,p}};(*for example*) For[y=2,y<=3,y++,For[z=2,z<=3,z++, matrix[[y,z]]=""]];(*or another placeholder*) manipulated=doSomeManipulations[Flatten[matrix]]; Partition[manipulated,4]//MatrixForm – Bill Apr 20 '18 at 15:53

a = SparseArray[RandomChoice[Range, {10, 5}]]; a[[Range[2, 4], Range[2, 4]]] = 0; SparseArray[a["NonzeroPositions"] -> manipulations[a["NonzeroValues"]]]

Where manipulations is the function you want to perform on the flattened values

• I need to flatten the non-zero entries to do the manipulations (not needed but this is because I am finding the nullspace of the a bunch of vectors stored on those positions of nonzero entries in the matrix.) – cleanplay Apr 20 '18 at 16:45
• In the above code a["NonzeroValues"] gives flattened non zero entries of the matrix a – no-one Apr 23 '18 at 15:41

Here's a function that is similar to @no-one's, but packaged differently:

nonzeroMap[func_, array_] := Replace[SparseArray[array],
Verbatim[SparseArray][a__, {b__, c_}] :> Normal @ SparseArray[a,{b,func/@c}]
]


A SparseArray object stores the nonzero elements in the last position of the last argument. So, the above function converts the input array into a SparseArray, maps func onto the nonzero elements, and then converts back to a normal array. Here are a couple examples:

random matrix

m = RandomInteger[3, {4,4}];
m //TeXForm


$\left( \begin{array}{cccc} 3 & 3 & 2 & 0 \\ 2 & 0 & 2 & 0 \\ 1 & 3 & 2 & 0 \\ 1 & 0 & 2 & 0 \\ \end{array} \right)$

nonzeroMap[1/#&, m] //TeXForm


$\left( \begin{array}{cccc} \frac{1}{3} & \frac{1}{3} & \frac{1}{2} & 0 \\ \frac{1}{2} & 0 & \frac{1}{2} & 0 \\ 1 & \frac{1}{3} & \frac{1}{2} & 0 \\ 1 & 0 & \frac{1}{2} & 0 \\ \end{array} \right)$

random array

a = RandomInteger[3, {3,3,3}];
a //TeXForm


$\left( \begin{array}{ccc} \{2,1,2\} & \{3,3,2\} & \{2,0,2\} \\ \{1,1,1\} & \{0,3,1\} & \{2,2,0\} \\ \{2,3,1\} & \{3,0,3\} & \{0,1,0\} \\ \end{array} \right)$

nonzeroMap[1/#&, a] //TeXForm


$\left( \begin{array}{ccc} \left\{\frac{1}{2},1,\frac{1}{2}\right\} & \left\{\frac{1}{3},\frac{1}{3},\frac{1}{2}\right\} & \left\{\frac{1}{2},0,\frac{1}{2}\right\} \\ \{1,1,1\} & \left\{0,\frac{1}{3},1\right\} & \left\{\frac{1}{2},\frac{1}{2},0\right\} \\ \left\{\frac{1}{2},\frac{1}{3},1\right\} & \left\{\frac{1}{3},0,\frac{1}{3}\right\} & \{0,1,0\} \\ \end{array} \right)$