8
$\begingroup$

I would like to swap rows with other rows or columns. Not for any particular size but for any size. I saw this detailed Q&A but it didn't answer my query.

I want to swap multiple rows or columns for a $N\times N$ (variable) matrix. I tried with lots of While and If loops but with no success.

How to write a program in Mathematica for this?

As an example, I am interested in swapping rows for an even $N$ as follows:

  • row 1 and $N$ are fixed,
  • row 2 becomes row 3, row 3 becomes row 2,
  • row 4 becomes row 5, row 5 becomes row 4,
  • and so on...

In Fortran this is trivial but how to implement this in Mathematica?

program swap // Fortran version
integer Ndim,i
Ndim=40
do, i=1:Ndim
    do, j=1:Ndim
      If(i<j)then
        matrix(i,j)=i+j
      endif
    enddo
enddo

Ndim=20
 do i=1,Ndim
    if (mod(j,2)==0 .and. j < Ndim) then
       matrix(i,j)=matrix(i,j+1)
    elseif(mod(j,2)!=0 .and. j<Ndim)then  // !=  not equal to
       matrix(i,j)=matrix(i,j-1)
    endif
 end do
end program

Any starting point will be very valuable. Thanks a lot for any help.

$\endgroup$
4
  • $\begingroup$ Can you elaborate on how the answers on the question you linked do not satisfy your need? $\endgroup$
    – Sascha
    Sep 23, 2016 at 9:25
  • $\begingroup$ Because it is for a specific case(like row 1 with 3 or otherwise). But if I have to swap many rows or columns, I can't write all of them explicitly. But inside a loop in a program. $\endgroup$
    – L.K.
    Sep 23, 2016 at 9:32
  • $\begingroup$ @lavkush You can always generate a list of indices that you want to swap. A loop is never needed for this purpose. $\endgroup$
    – C. E.
    Sep 23, 2016 at 9:33
  • $\begingroup$ @m_goldberg It isn't, in the question explained it clearly. Because any sort of swapping not only some particular type but also size can be any, so choice of indices $\endgroup$
    – L.K.
    Sep 23, 2016 at 14:36

2 Answers 2

9
$\begingroup$

Swapping rows

Code.

swapRows[matrix_?SquareMatrixQ] /; EvenQ[Length[matrix]] := 
     Module[{mat = matrix, r = Range[2, Length[matrix] - 1]}, 
         mat[[r]] = mat[[Flatten[Reverse /@ Partition[r, 2]]]];
         mat
     ];

Usage.

mat = Partition[Range[36], 6];
mat // MatrixForm

enter image description here

swapRows[mat] // MatrixForm

enter image description here

Swapping columns

Code.

swapColumns[matrix_?SquareMatrixQ] /; EvenQ[Length[matrix]] := 
     Module[{mat = matrix, r = Range[2, Length[matrix] - 1]}, 
         mat[[All, r]] = mat[[All, Flatten[Reverse /@ Partition[r, 2]]]];
         mat
     ];

Usage.

swapColumns[mat]

enter image description here

Comments

For other swappings, you will need to generate the list of rows or columns you want to swap in the appropriate way, as mentioned by C.E. in his comment.

$\endgroup$
4
$\begingroup$

The Do loop comes to mind:

swapR[mat_] := Block[{mat1},
  mat1 = ConstantArray[0, Length@mat];
  Do[
   mat1[[1]] = mat[[1]];
   mat1[[Length@mat]] = mat[[Length@mat]];
   mat1[[{i, i + 1}]] = mat[[{i + 1, i}]];,
   {i, 2, Length@mat - 2, 2}
   ];
  mat1
  ]

swapC[mat_] := Block[{mat1, matT = Transpose@mat},
  mat1 = ConstantArray[0, Length@mat];
  Do[
   mat1[[1]] = matT[[1]];
   mat1[[Length@matT]] = matT[[Length@matT]];
   mat1[[{i, i + 1}]] = matT[[{i + 1, i}]];,
   {i, 2, Length@matT - 2, 2}
   ];
  Transpose@mat1
  ]

The idea of swapR is to define a new matrix, mat1, with its first and last rows the same as the input matrix mat. The other rows are interchanged pairwise with the line mat1[[{i, i + 1}]] = mat[[{i + 1, i}]] - this swaps row i and i+1. An (un-tested in the code) assumptions is that there is an even number of rows, so it has to go through i = 2, 4, ..., hence the iterator of the Do loop.

Swapping columns is equivalent to swapping rows of a transposed matrix and transposing the result, hence the Transpose in inserted in the swapC code.

The RepeatedTimings are practically the same as with Xavier's approach.


EDIT: The above codes answer explicitly the OP. A more flexible approach will be as follows.

To swap any two rows i and j of a general $m\times n$ matrix:

swapRij[mat_, {i_, j_}] := Block[{mat1 = mat},
  mat1[[{i, j}]] = mat[[{j, i}]];
  mat1
  ]

Usage: swapRij[mat, {1, 2}] swaps the first and second rows of mat. Note the second argument is a list.

Similarly, to swap any two columns i and j:

swapCij[mat_, {i_, j_}] := Block[{matT = Transpose@mat},
  matT[[{i, j}]] = matT[[{j, i}]];
  Transpose@matT
  ]

The functions swapRij and swapCij can be used on a set of pairs of rows/columns to be swapped. Let's take e.g. mat = Partition[Range[36], 6] and do

Fold[swapRij[#1, #2] &, mat, {{1, 2}, {3, 4}, {5, 6}}]

swaps the 1st and 2nd, 3rd and 4th, and 5th and 6th rows:

enter image description here

Similarly for Folding swapCij.

$\endgroup$
6
  • $\begingroup$ Swapping using Do loop $\endgroup$
    – L.K.
    Sep 23, 2016 at 14:21
  • $\begingroup$ Can you little bit explain it. It will be of great help. Because I would like to change only the rows (1->2, 2-> 1) and 3->4, 4->3 but last two rows not changing. Would like to learn the code. So that I can learn all the possibilities $\endgroup$
    – L.K.
    Sep 23, 2016 at 14:24
  • $\begingroup$ Explanation helped, and I was able to do my own swapping. Thanks a lot for this. $\endgroup$
    – L.K.
    Sep 23, 2016 at 14:41
  • $\begingroup$ mat = V1; swapR[mat_] := Block[{mat1}, mat1 = ConstantArray[0, Length@mat]; Do[mat1[[1]] = mat[[1]]; mat1[[Length@mat]] = mat[[Length@mat]]; mat1[[{i, i + 1}]] = mat[[{i + 1, i}]];, {i, 2, Length@mat - 2, 2}]; mat1] MatrixForm[mat1]. But no display of mat1. V1 is properly defined. $\endgroup$
    – L.K.
    Sep 24, 2016 at 10:59
  • $\begingroup$ ??? mat1 is local, as indicated by the first argument of Block; swapR[V1] is the output. Read how to define and work with functions. $\endgroup$
    – corey979
    Sep 24, 2016 at 11:39

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