8
$\begingroup$

I'm applying a calculation to a block from a 6x6 matrix. I get the block by using Part. For example:

kept={1, 2, 4, 5, 6}
KBB=mk[[kept,kept]]

where mk is my 6x6 matrix. So the above code, basically removes row 3 and column 3 and puts into KBB the resulting 5x5 matrix.

Then I apply several calculations to KBB and, at the end, I want to "undo" the work done by Part.

So, now I want to "send" the rows and columns from KBB back to a new 6x6 matrix, at positions {1, 2, 4, 5, 6} while filling any undefined row/columns with zeroes (in this example, the third row and column should be all zeroes in the result).

Note that this example only removes one row and column, but it could be two, three, four, or five.

I mean, I need to apply this transformation to very different cases such as:

kept={1,2,3,5}
kept={1,3,5}
kept={6}

In all cases, the final matrix must be again 6x6, just like the original one.

Isn't there any opposite of Part? Any sort of row/column remapping command?

$\endgroup$
  • 2
    $\begingroup$ @CarlWoll I did read that topic before posting. While it discusses column/row swapping, I didn't find any trace of doing what I need, except by a two-pass operation (first operate in columns in first-pass, then on rows on second pass). $\endgroup$ – cesss Jul 15 '17 at 16:50
  • $\begingroup$ To the people who marked this as duplicate: Please consider extending the solutions given in the question you thought to be duplicate of this, so that the case of inserting a matrix block (not a row or column, but a matrix block) inside of another matrix is addressed there. Then, yes, you will be able to affirm that the same concept has been discussed twice. Although, honestly, I wouldn't be sure which one is duplicate of which, considering I asked about matrix blocks first. $\endgroup$ – cesss Jul 16 '17 at 12:05
  • $\begingroup$ (1) cesss, I didn't see your comment to Carl before joining in the vote to close. (2) Nevertheless I feel that if one understands (especially my answer to) the previous question this one is naturally solved. (3) I extended my answer with additional examples to make this capability explicit, and you suggested above. (4) Please understand that your question even if marked as a duplicate remains visible and valid (for votes, badges, etc.) and serves as a guidepost for the master question. (5) All this notwithstanding if others feel this should be reopened they may vote to. $\endgroup$ – Mr.Wizard Jul 16 '17 at 20:32
  • $\begingroup$ @Mr.Wizard : I don't have an special interest in keeping the question open, as I got the answer I needed before the question was closed, and also because, as you said, the stuff here is available to future visitors. Moreover, I believe (this is a personal guess) that users who in the future search how to insert sub-blocks of matrices into larger matrices will have their search engine pointing here before than to the question this one supposedly duplicates, because that one is focused in row and column operations (as the title implies), while this is focused in matrix blocks. $\endgroup$ – cesss Jul 16 '17 at 20:48
11
$\begingroup$

Do you mean this?

mk = RandomReal[{-1, 1}, {6, 6}];
kept = {1, 2, 4, 5, 6}
KBB = mk[[kept, kept]]

newmk = ConstantArray[0., Dimensions[mk]];
newmk[[kept, kept]] = KBB;
newmk
$\endgroup$
  • $\begingroup$ Just use = instead of += $\endgroup$ – Carl Woll Jul 15 '17 at 16:49
  • $\begingroup$ It works beautifully, thanks a lot!! I didn't consider that Part could be used for modifying a part of a matrix, not only extracting it. Thanks!! $\endgroup$ – cesss Jul 15 '17 at 16:52
  • $\begingroup$ @Cael Woll: Yes, you are right. I corrected that. $\endgroup$ – Henrik Schumacher Jul 15 '17 at 16:52
  • $\begingroup$ You're welcome. $\endgroup$ – Henrik Schumacher Jul 15 '17 at 16:54
3
$\begingroup$

Henrik's answer gives the most straightforward and convenient way. An alternative, at the cost of two extra pairs of braces, is to use SparseArray[{{0}}, Dimensions@m] instead of ConstantArray[0, Dimensions@m].

A function that takes two matrices, (m and k), and a list of keptrows and keptcols as input, and produces a SparseArray with the dimensions of m where the values at cells corresponding to the kept rows and columns are set to the values of the matrix k:

ClearAll[saF]
saF[m_, k_, {keptrows_, keptcols_}] := 
 Module[{sa = SparseArray[{{0}}, Dimensions@m]}, sa[[keptrows, keptcols]] = k; sa]

Examples:

SeedRandom[1]
mk = RandomInteger[9, {6, 6}];
keptrows = keptcols = {1, 2, 4, 5, 6};
kbb = mk[[keptrows, keptcols]];

saF[mk, kbb, {keptrows, keptcols}] // Normal // TeXForm

$ \left( \begin{array}{cccccc} 2 & 1 & 0 & 9 & 7 & 5 \\ 7 & 2 & 0 & 3 & 6 & 3 \\ 0 & 0 & 0 & 0 & 0 & 0 \\ 3 & 7 & 0 & 4 & 1 & 4 \\ 9 & 1 & 0 & 7 & 6 & 7 \\ 8 & 1 & 0 & 2 & 8 & 5 \\ \end{array} \right)$

aa = Array[a, {8, 7}];
keptrows = {2, 4, 6, 7};
keptcols = {1, 5, 6};
kaa = aa[[keptrows, keptcols]] /. a -> b;
saF[aa, kaa, {keptrows, keptcols}] // Normal // TeXForm

$ \left( \begin{array}{ccccccc} 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ b(2,1) & 0 & 0 & 0 & b(2,5) & b(2,6) & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ b(4,1) & 0 & 0 & 0 & b(4,5) & b(4,6) & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ b(6,1) & 0 & 0 & 0 & b(6,5) & b(6,6) & 0 \\ b(7,1) & 0 & 0 & 0 & b(7,5) & b(7,6) & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ \end{array} \right)$

$\endgroup$
  • $\begingroup$ Another alternative is to use Band. I'm curious which way is faster. $\endgroup$ – Alexey Popkov Jul 16 '17 at 16:35
  • $\begingroup$ @AlexeyPopkov, I couldn't think of a way to use Band in this case. $\endgroup$ – kglr Jul 16 '17 at 16:44
  • $\begingroup$ Citing the Docs: "Insert a submatrix beginning at position 3, 3: SparseArray[Band[{3, 3}] -> {{a, b}, {c, d}}, {5, 5}]." $\endgroup$ – Alexey Popkov Jul 16 '17 at 16:50
  • 1
    $\begingroup$ @Alexey, I meant, in this case, (since we are note inserting a single submatrix), it would be quite a challenge to find the appropriate sub-blocks of kbb and their starting positions in the sparse array to use Band. $\endgroup$ – kglr Jul 16 '17 at 17:26
  • $\begingroup$ You are right, I misread the question. $\endgroup$ – Alexey Popkov Jul 16 '17 at 17:37
2
$\begingroup$

This is a version which doesn't require modifying a matrix in place, although it is the same basic idea. I use a background matrix of zeroes, the set replace at positions construct from kept from the corresponding positions in KBB (which depend only on the length of kept):

z = Array[0 &, {6, 6}];
ReplacePart[
    z, 
    MapThread[
         #1 -> Extract[KBB, #2] &, 
         {Tuples[kept, 2], Tuples[Range[Length[kept]], 2]}
    ]
]
$\endgroup$

Not the answer you're looking for? Browse other questions tagged or ask your own question.