7
$\begingroup$

I have the following self-explanatory question.

https://1drv.ms/u/s!AsyHs3E_aioxhipb3wSPSX_heN-t

enter image description here

As seen from the above matrices, I start with the "original" matrix, which is a symmetric matrix, meaning that first row and first column represent the same variable, say X, and 2nd row and 2nd column represent the variable Y, following Z, W, V. I first want to move 2nd row in the "original" matrix to 4th row. This operation is shown in the matrix denoted by r24. After this operation, I want to do the same operation on the same columns, meaning that I want to move 2nd column to 4th column as shown in c24. All of these operations are shown with the colored text. The resulting final matrix, which I aim to create, c24, should be symmetric with respect to the variable names. It means that the final matrix has the ordered variable names as X, Z, W, Y, V in columns and rows. In fact, if the above two operations are done correctly, the order of the variables in rows and columns will remain identical.

I like to do all the operations using a Mathematica function such as f[original, 2, 4] to create the final matrix c24.

Thank you all.

$\endgroup$
2
  • 1
    $\begingroup$ closely related/ possible duplicate: Move element inside a list $\endgroup$
    – kglr
    Commented Mar 20, 2019 at 17:21
  • 1
    $\begingroup$ FWIW: your matrix is called a Hankel matrix. HankelMatrix[Range[5], Range[5, 9]] $\endgroup$ Commented Mar 23, 2019 at 12:45

6 Answers 6

6
$\begingroup$

Simply use Part and Set:

f[A_?SquareMatrixQ, i_Integer, j_Integer] := Module[{p, idx},
 idx = Range[i, j, Sign[j - i]];
 p = Range[1, Length[A]];
 p[[idx]] = RotateLeft[idx];
 A[[p, p]]
 ]

A = Outer[Plus, Range[5], Range[0, 4]];
A // MatrixForm

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

B = f[A,2,4];
B // MatrixForm

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

$\endgroup$
6
  • $\begingroup$ Your answer is very good, with one slight change. When you move the 2nd row to 4th row, the order of the rows should remain unchanged. It means that when you move the 2nd row, the 3rd and 4th rows should just be moved up without changing the order. Of course the same applies to the column movements. This is important for my purpose and that is why I gave a name for rows and columns. Thank you very much for your very quick answer. $\endgroup$ Commented Mar 20, 2019 at 14:03
  • $\begingroup$ @TugrulTemel I see. Is this better now? I am not sure if the case $i>j$ is handled as you expect. $\endgroup$ Commented Mar 20, 2019 at 14:16
  • $\begingroup$ Excellent...that is what I aim to achieve. Really, thank you so much for your prompt answer. regards, Tugrul $\endgroup$ Commented Mar 20, 2019 at 14:34
  • 1
    $\begingroup$ You didn't reply, but anyway: q = Range[i, j, Sign[j - i]]; p = RotateLeft[q]; $\endgroup$
    – Mr.Wizard
    Commented Mar 21, 2019 at 23:20
  • 3
    $\begingroup$ @Mr.Wizard Sorry, I've been out tonight. This won't happen again, I promise ;) Thank you, that is indeed simpler. I took the freedom to incorporate that into my solution (in an updated version with more performance). $\endgroup$ Commented Mar 21, 2019 at 23:35
6
$\begingroup$

to move a row from $i$ to $j$:

rowmove[A_?MatrixQ, i_Integer, j_Integer] := Insert[Delete[A, i], A[[i]], j]

to move a column from $i$ to $j$:

colmove[A_?MatrixQ, i_Integer, j_Integer] := Transpose@rowmove[Transpose[A], i, j]

both at the same time:

move[A_?MatrixQ, i_Integer, j_Integer] := colmove[rowmove[A, i, j], i, j]
$\endgroup$
3
  • $\begingroup$ Clean solution, copying it... $\endgroup$
    – MikeY
    Commented Mar 20, 2019 at 14:54
  • 1
    $\begingroup$ Here is somewhat simplified version of your solution f[A_?MatrixQ, i_Integer, j_Integer] := (B = Insert[Delete[A, i], A[[i]], j]; Insert[Delete[Transpose@B, i], B[[All, i]], j]) or this one g[A_?MatrixQ, i_Integer, j_Integer] := (B = Transpose@Insert[Delete[A, i], A[[i]], j]; Transpose@Insert[Delete[B, i], B[[i]], j]) $\endgroup$ Commented Mar 21, 2019 at 13:40
  • $\begingroup$ @OkkesDulgerci I don't think it's a good idea to use global variables like B in a function definition. Instead, I'd use With or Module to make the variable local. $\endgroup$
    – Roman
    Commented Mar 21, 2019 at 14:58
5
$\begingroup$

Define the indices that you want to interchange in a list $ind$ and then you can index into the array $a$ directly.

a = {{1, 2, 3, 4, 5}, {2, 3, 4, 5, 6}, {3, 4, 5, 6, 7},
     {4, 5, 6, 7, 8}, {5, 6, 7, 8, 9}}; 
ind = {1, 3, 4, 2, 5};
a[[ind, ind]]

If you don't want to specify the index array each time, Roman points out that you can build a simple function to do it:

indexlist[n_, i_, j_] := Insert[Delete[Range[n], i], i, j]

So to get the above you would specify

ind = indexlist[5,2,4]
$\endgroup$
1
  • $\begingroup$ You can get the index list ind with indexlist[n_, i_, j_] := Insert[Delete[Range[n], i], i, j]. In this case, indexlist[5, 2, 4] will give {1, 3, 4, 2, 5}. $\endgroup$
    – Roman
    Commented Mar 21, 2019 at 1:23
2
$\begingroup$
hm = HankelMatrix[Range[5], Range[5, 9]];

MatrixForm@hm

enter image description here

Using Permute and Cycle to determine the ordering:

ord = Permute[Range[5], Cycles[{{4, 3, 2}}]]

(*{1, 3, 4, 2, 5}*)

Applying the ordering to move 2nd row of hm to 4th row:

rm = hm[[ord]];

MapAt[Style[#, Bold, Red] &, {{4, All}, {All, 2}}]@rm // MatrixForm

enter image description here

Applying the ordering to move 2nd column of rm to 4th column:

cm = (Transpose@rm)[[ord]];

MapAt[Style[#, Bold, Darker@Blue] &, {{4, All}, {All, 4}}]@cm // MatrixForm

enter image description here

$\endgroup$
2
$\begingroup$

Using SubsetMap (new in 12.0)

om = HankelMatrix[Range[5], Range[5, 9]];

om // MatrixForm

enter image description here

Move 2nd row of om to 4th row

rm = SubsetMap[RotateLeft, om, {2, 3, 4}];

rm // MatrixForm

enter image description here

Move 2nd column of rm to 4th column

cm = Query[All, SubsetMap[RotateLeft, #, {2, 3, 4}] &] @ rm;

MapAt[Style[#, Bold]&, {{4, All}, {All, 4}}] @ cm // MatrixForm

enter image description here

Addendum

To swap rows (instead of moving) we omit the middle 3:

SubsetMap[RotateLeft, om, {2, 4}] // MatrixForm

enter image description here

$\endgroup$
1
$\begingroup$
f[A_?MatrixQ, i_Integer, j_Integer] := With[{B = Transpose@Insert[Delete[A, i], A[[i]], j]}, 
  Transpose@Insert[Delete[B, i], B[[i]], j]]
f[A, 2, 4] // MatrixForm
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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