208
$\begingroup$

Question

The Mathematica tutorial has a section 'Basic Matrix Operations', describing operations like transpose, inverse and determinant. These operations all work on entire matrices. I am missing a section on basic operations on matrix rows / columns.

For example:

  1. Extracting a row from a matrix
  2. Inserting a row into a matrix
  3. Adding two rows within a matrix together
  4. Swapping two rows
  5. Multiplying a row with a number

And similar for columns.

What is the most elegant way to implementation of these operations? Speed is not important for me, but simplicity is.

Summary

Here I summarize my personal taste. I will update it whenever someone suggests a way I like more.

m = Range@12 ~Partition~ 3;
m // MatrixForm

$\begin{pmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \\ 10 & 11 & 12 \end{pmatrix}$

Insert a column at position 2:

v = Range[21, 24];
Insert[m // Transpose, v, 2] // Transpose // MatrixForm

$\begin{pmatrix} 1 & 21 & 2 & 3 \\ 4 & 22 & 5 & 6 \\ 7 & 23 & 8 & 9 \\ 10 & 24& 11 & 12 \end{pmatrix}$

Extract row / column

Extract row 2:

m[[2]]

$(4,5,6)$

Extract column 2

m[[All, 2]] // MatrixForm

$\begin{pmatrix}2\\5\\8\\11\end{pmatrix}$

Insert a row / column

Insert a row at position 2:

v = Range[13, 15];
Insert[m, v, 2] // MatrixForm

$\begin{pmatrix} 1 & 2 & 3 \\ 13 & 14 & 15 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \\ 10 & 11 & 12 \end{pmatrix}$

Adding two rows / columns

column 3 = column 3 + column 1:

m2 = m;  
m2[[All, 3]] += m2[[All, 1]];
m2 // MatrixForm

$\begin{pmatrix} 1 & 2 & 4 \\ 4 & 5 & 10 \\ 7 & 8 & 16 \\ 10 & 11 & 22 \end{pmatrix}$

row 2 = row 2 + row 3:

m2 = m;
m2[[2]] += m2[[3]];
m2 // MatrixForm

$\begin{pmatrix} 1 & 2 & 3 \\ 11 & 13 & 15 \\ 7 & 8 & 9 \\ 10 & 11 & 12 \end{pmatrix}$

Swapping rows / columns

Swap row 1 and row 3:

m2 = m;
m2[[{1, 3}]] = m2[[{3, 1}]];
m2 // MatrixForm

$\begin{pmatrix} 7 & 8 & 9 \\ 4 & 5 & 6 \\ 1 & 2 & 3 \\ 10 & 11 & 12 \end{pmatrix}$

Swap column 1 and 3:

m2[[All, {1, 3}]] = m2[[All, {3, 1}]];
m2 // MatrixForm

$\begin{pmatrix} 3 & 2 & 1 \\ 6 & 5 & 4 \\ 9 & 8 & 7 \\ 12 & 11 & 10 \end{pmatrix}$

Multiplying rows / columns

Multiply row 2 with 2:

m*{1, 2, 1, 1} // MatrixForm

$\begin{pmatrix} 1 & 2 & 3 \\ 8 & 10 & 12 \\ 7 & 8 & 9 \\ 10 & 11 & 12 \end{pmatrix}$

Multiply column 1 with 5:

 ((m // Transpose)*{5, 1, 1}) // Transpose // MatrixForm

$\begin{pmatrix} 5 & 2 & 3 \\ 20 & 5 & 6 \\ 35 & 8 & 9 \\ 50 & 11 & 12 \end{pmatrix}$

References

$\endgroup$
5
  • 5
    $\begingroup$ you dont need All` to get a row. m[[2]] and m[[2,All]] both give the second row of m. $\endgroup$
    – kglr
    Commented Mar 16, 2012 at 8:37
  • $\begingroup$ What about a partial column, say column one and first three rows, say using your example to get 1, 4, 7? I tried mat[[{1, 3}, 1]] // MatrixForm -> {1},{7}, but I want {1},{4},{7}? $\endgroup$ Commented Jan 15, 2013 at 16:54
  • $\begingroup$ ok got it, need to Transpose, Flatten, Take as in: Take[Flatten[Transpose[mat]], {1, 3}] -> {1,4,7}, unless there are betters way to do so? $\endgroup$ Commented Jan 15, 2013 at 17:16
  • 1
    $\begingroup$ How about deleting a row or column? $\endgroup$
    – Hirek
    Commented Feb 28, 2015 at 19:00
  • 2
    $\begingroup$ @Hirek, you'll want to look up Drop[] and Delete[]. $\endgroup$ Commented Jun 18, 2015 at 9:35

15 Answers 15

70
$\begingroup$

I like to use Part even when I don't want to modify the original matrix. This of course requires making a copy but it keeps syntax more consistent.

adding column one to column three:

m = Range@12 ~Partition~ 3;
m // MatrixForm

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

m2 = m;

m2[[All, 3]] += m2[[All, 1]];

m2 // MatrixForm

$\left( \begin{array}{ccc} 1 & 2 & 4 \\ 4 & 5 & 10 \\ 7 & 8 & 16 \\ 10 & 11 & 22 \end{array} \right)$

With an external vector:

v = {-1, -2, -3, -4};

m2 = m;

m2[[All, 3]] += v;

m2 // MatrixForm

$\left( \begin{array}{ccc} 1 & 2 & 2 \\ 4 & 5 & 4 \\ 7 & 8 & 6 \\ 10 & 11 & 8 \end{array} \right)$

swapping rows and columns:

m2 = m;

m2[[{1, 3}]] = m2[[{3, 1}]];

m2 // MatrixForm

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

m2 = m;

m2[[All, {1, 3}]] = m2[[All, {3, 1}]];

m2 // MatrixForm

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


Simultaneous row-and-column operations

Part is capable of working with rows and columns simultaneously(1).

We can operate on (or replace) a contiguous sub-array:

m2 = m;

m2[[3 ;;, 2 ;;]] /= 5;

m2 // MatrixForm

$\left( \begin{array}{ccc} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & \frac{8}{5} & \frac{9}{5} \\ 10 & \frac{11}{5} & \frac{12}{5} \\ \end{array} \right)$

Or a disjoint specification:

m2 = m;

m2[[{1, 2, 4}, {1, 3}]] = 0;

m2 // MatrixForm

$\left( \begin{array}{ccc} 0 & 2 & 0 \\ 0 & 5 & 0 \\ 7 & 8 & 9 \\ 0 & 11 & 0 \\ \end{array} \right)$

Or construct a new array from constituent parts in arbitrary order:

mx = BoxMatrix[2] - 1;

mx[[{1, 2, 5, 4}, {4, 5, 1}]] = m;

mx // MatrixForm

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

$\endgroup$
4
  • 1
    $\begingroup$ +1. Agreed: part is just so flexible and convenient it's often the nicest way to go about these. $\endgroup$
    – Szabolcs
    Commented Mar 17, 2012 at 7:36
  • $\begingroup$ Just ask: Why won't the code m2[[All, {1, 3}]] = m2[[All, {3, 1}]]; just give column 1 and 3 indentical? First you assign column 3 to column 1, then you assign column 1 to column 3, which has already become the original column 3... $\endgroup$ Commented Dec 29, 2015 at 11:58
  • $\begingroup$ @buzhidao I don't know if I can explain this clearly for you since it seems I failed the first time. There is only a single assignment in that expression, and only a single reversal of columns. It might be translated to "let columns 1 and 3 be set to columns 3 and 1". A simpler example without columns is a = {1, 2, 3, 4, 5}; then a[[{1, 3}]] = a[[{3, 1}]]; after which a is {3, 2, 1, 4, 5}. $\endgroup$
    – Mr.Wizard
    Commented Dec 30, 2015 at 0:10
  • $\begingroup$ @buzhidao Help on WhenEvent discusses something alike: sequential actions modify variables in turn, e.g. {x[t] -> y[t], y[t] -> x[t]}, while simultaneous actions swap, e.g. {x[t], y[t]} -> {y[t], x[t]}. I think this is idiomatic to the system. $\endgroup$
    – BoLe
    Commented Jul 30, 2016 at 9:59
38
$\begingroup$

Interchanging rows

This'll swap rows 1 and 3.

Permute[mat, Cycles[{{1, 3}}]]

To swap columns, you can convert the permutation to a permutation list,

permList = PermutationList[Cycles[{{1, 3}}], Last@Dimensions[mat]]

then use

mat[[All, permList]]

Multiplying rows

This'll multiply the 3rd row by 5:

MapAt[5 # &, mat, 3]

This'll change the matrix permanently:

mat[[3]] *= 5
$\endgroup$
2
  • $\begingroup$ I believe one would need to take care to keep the length of the permutation list the same. As PermutationList[Cycles[{{m,n}}]] will range from 1 to Max[{m,n}]. And so mat[[All, permList]] would perhaps give a smaller matrix than intended. $\endgroup$
    – Kvothe
    Commented Oct 17, 2018 at 9:46
  • $\begingroup$ @Kvothe Thanks, updated. $\endgroup$
    – Szabolcs
    Commented Oct 17, 2018 at 10:53
28
$\begingroup$

For small matrices, using simple indexing might be more readable:

Interchanging rows:

m[[{1, 3, 2}]]

Multiplying rows:

m * {1,2,1}

Adding rows

m + {0,v,0}

For large matrices, you could use SparseArray to generate the second matrix (less readable, but works for any matrix size and might be faster, too):

m * SparseArray[2 -> 2, Length[m], 1]
m + SparseArray[2 -> v, Length[m], 0]

Insert a row into a matrix

Insert[m, v, 2]

You might want to look at the Matrix and Tensor Operations tutorial, too

$\endgroup$
3
  • $\begingroup$ For multiplying and adding rows---I agree it's likely the most efficient way. Can you show your preferred way to generate those vectors ({1,2,1} and {0,v,0}) if the matrix is large? I miss a way equivalent to mat[[2]] *= 2 which returns a copy instead of modifying the matrix. $\endgroup$
    – Szabolcs
    Commented Mar 16, 2012 at 10:22
  • $\begingroup$ @Szabolcs: Isn't m * {1,2,1} the functional equivalent to mat[[2]] *= 2? $\endgroup$ Commented Mar 16, 2012 at 10:57
  • $\begingroup$ If it's a 10 by 10 matrix, and you want the 7th elements, you have to write {1,1,1,1,1,1,3,1,1,1} and make sure that you inserted 3 in the correct position. This is tedious and error prone. This is why I asked how you prefer to generate that vector. $\endgroup$
    – Szabolcs
    Commented Mar 16, 2012 at 10:59
26
$\begingroup$

These are ancient routines I have been using a long time ago. As a matter of fact, it's been so long that I do not even remember if I wrote them or simply shamelessly took them from some other source. Back at the time the only sources I had at my disposal where The Mathematical Journal (prior to 1998 or 1999), Bahder's wonderful book (which is the most likely source, at least of inspiration, given the style), Mathematica By Example (first edition) by Abell and Braselton and... Matlab for Engineers (LOL, I'm not kidding) by Biran and Breiner. The reason I am not sure to be the author myself is because these procedures appear too smart for me to have conceived them :-). If someone can trace the original source, I will give it due credit.

Main procedures:

row[A_,n_]:=A[[n]]
col[A_,n_]:=#[[n]]& /@ A
Col[A_,n_]:={#[[n]]}& /@ A

col returns the column in the form {x1,x2,...} Col returns it as {{x1},{x2},...} ("vertical" vector)

Smart applying:

row /: (row[A_,n_]=r_):=(A[[n]]=r)
col /: (col[A_,n_]=c_):=(A[[ Range[Dimensions[A][[1]]],{n} ]]=(List /@ c)) 
Col /: (Col[A_,n_]=c_):=(A[[ Range[Dimensions[A][[1]]],{n} ]]=c) 
row /: (row[A_,n_]:=r_):=(A[[n]]:=r)
col /: (col[A_,n_]:=c_):=(A[[ Range[Dimensions[A][[1]]],{n} ]]:=(List /@ c))
Col /: (Col[A_,n_]:=c_):=(A[[ Range[Dimensions[A][[1]]],{n} ]]:=c)

Now... here is how to use them. Let's start with a matrix

A={
{1,2,3}, 
{4,5,6}, 
{7,8,9}
}; 

Suppose you want to replace the second column of A with 100 times its value. All you need to do is to tell Mathematica what is the new value of the column, for example 100 times its current value:

col[A,2]=100*col[A,2] 

{200,500,800}

The side effect of col is to show the new value of the column, but its primary and intended effect is to change the original matrix A accordingly:

A

{ {1,200,3}, {4,500,6}, {7,800,9} }

row can be used in the same way. Suppose we want to substitute the first row with a linear combination of all three rows of A

row[A, 1] = row[A, 1] + 2 row[A, 2] - row[A, 3]

{2, 400, 6}

The original matrix A is changed accordingly.

A

{ {2,400,6}, {4,500,6}, {7,800,9} }

Basically these procedures allow one to do all the operations he or she wishes on rows and columns of a matrix. Extracting, defining, substituting with linear combinations or whatever comes to one's mind. As mentioned before, if one desires to extract a column in the form {{a},{b},{c}}, he should use Col instead of col.

Pretty col, uh?

EDIT: I just found a more elaborate notebook with "the making of" written by me where I refer to "Thomas Bahder's MMA for Scientists and Engineers", "Bruce Ikenaga'a Matrix Operations" and "me" as sources. So perhaps I was the author of the wrappers... Later this week I will add the procedures for joining, inserting, appending and swapping rows and columns and I will try to ascertain who wrote what.

$\endgroup$
20
$\begingroup$

Not as simple as the other solutions, but the linear-algebraic treatment might be convenient in some applications:

m = Partition[Range[12], 3];

Add column 2 and column 3, and store result in column 3:

m.SparseArray[{Band[{1, 1}] -> 1, {1, 3} -> 1}, ConstantArray[Last[Dimensions[m]], 2]]

Add row 2 and row 3, and store result in row 2:

SparseArray[{Band[{1, 1}] -> 1, {2, 3} -> 1}, ConstantArray[First[Dimensions[m]], 2]].m

Multiply second row by 2:

ReplacePart[IdentityMatrix[First[Dimensions[m]]], {2, 2} -> 2].m

Multiply first column by 5:

m.ReplacePart[IdentityMatrix[Last[Dimensions[m]]], {1, 1} -> 5]
$\endgroup$
19
$\begingroup$

Inserting columns (recycling answers from here).

m = Range@12~Partition~3;
m // MatrixForm
v = Range[21, 24];

MapThread[Insert, {m, v, Table[2, {Length[v]}]}] // MatrixForm

Table[Insert[m[[i]], v[[i]], 2], {i, Length[v]}] // MatrixForm

enter image description here

$\endgroup$
5
  • $\begingroup$ How to put this numbers in index, for example A1,A2,A3,A4..A12? m = Range@12 ~Partition~ 3; m // MatrixForm $\endgroup$ Commented Apr 16, 2012 at 14:14
  • $\begingroup$ Do you mean like this? Clear[A]; Print[ MatrixForm[m = Outer[A, {1, 2, 3, 4}, {1, 2, 3}]]]; v = Range[21, 24]; MapThread[Insert, {m, v, Table[2, {Length[v]}]}] // MatrixForm $\endgroup$ Commented Apr 16, 2012 at 18:45
  • $\begingroup$ Or perhaps like this: Print[MatrixForm[m = Range@12~Partition~3]]; Clear[A]; Print[ v = Array[A, 4]]; MapThread[Insert, {m, v, Table[2, {Length[v]}]}] // MatrixForm $\endgroup$ Commented Apr 17, 2012 at 8:15
  • 2
    $\begingroup$ Do we have to build Table[2, {Length[v]}]? IMO MapThread[Insert[#1, #2, 2] &, {m, v}] is cleaner. $\endgroup$
    – Yi Wang
    Commented Apr 15, 2014 at 13:01
  • 1
    $\begingroup$ It's just an alternative form. I prefer MapThread too, although now I have seen another method from Kuba: Efficient method for Inserting arrays into arrays. $\endgroup$ Commented Apr 15, 2014 at 13:07
19
$\begingroup$

There are some internal, undocumented functions for row and columns operations:

(* in-place(!) transformation of the matrix *)
Statistics`Library`MatrixRowTranslate[matrix, vector]
Statistics`Library`MatrixRowTimes[matrix, vector]
Statistics`Library`MatrixRowAffineTransform[matrix, vector, vector] (* mat, times, xlate *)
Statistics`Library`MatrixRowAffineTransform[matrix, scalar, vector]
(* returns vector *)
Statistics`Library`MatrixColumnSum[matrix]
Statistics`Library`MatrixRowSum[matrix]

The first four have the inelegance, admittedly, of modifying the argument matrix in place, and so are not well-suited for functional programming. On the other hand, all six are efficient, especially on numeric arrays, packed or unpacked. Perhaps the OP's original scope does not comprise all these operations, although it is somewhat open-ended; however, I thought that since they are strongly related, it would be better to have them all here than in a separate Q&A.

Note that a vector argument can easily be a row or column of matrix, but the whole matrix will be transformed in those cases.

Examples

mm = {
   {a, b, c},
   {d, e, f},
   {g, h, i},
   {j, k, l}
  };

Add a vector to each row:

Module[{res = mm},
  Statistics`Library`MatrixRowTranslate[res, {u, v, w}];
  res] // MatrixForm

Mathematica graphics

Multiply each row by a vector: It's elementwise scalar multiplication, the same as row * vector, for each row in the matrix.

Module[{res = mm},
  Statistics`Library`MatrixRowTimes[res, {x, y, z}];
  res] // MatrixForm

Mathematica graphics

Multiply each column by a vector: Times already does what the missing MatrixColumnTimes[] would do:

mm*{w, x, y, z} // MatrixForm

Mathematica graphics

Affine transformation of the rows: The MatrixRowAffineTransform can be viewed as multiplying the row by {x, y, z}] and adding the second vector {u, v, w}, or as operating on the columns threading the components of the vectors.

Module[{res = mm},
  Statistics`Library`MatrixRowAffineTransform[res, {x, y, z}, {u, v, w}];
  res] // MatrixForm

Mathematica graphics

MatrixRowAffineTransform allows the scaling argument to be a scalar.

Module[{res = mm},
  Statistics`Library`MatrixRowAffineTransform[res, x, {u, v, w}];
  res] // MatrixForm

Mathematica graphics

Affine transformation of the columns: Again, Times and Plus supply the missing MatrixColumnAffineTransform[]:

mm * {w, x, y, z} + {p, q, r, s} // MatrixForm

Mathematica graphics

Summing rows or columns:

Statistics`Library`MatrixColumnSum[mm]
(*  {a + d + g + j, b + e + h + k, c + f + i + l}  *)

Statistics`Library`MatrixRowSum[mm]
(*  {a + b + c, d + e + f, g + h + i, j + k + l}  *)

Timings of the sums can be found here. Since the OP explicitly said speed was not an issue, I didn't want to clutter this post with timings. Nonetheless, these are, as I mentioned, fast on numeric arrays.

$\endgroup$
2
  • 3
    $\begingroup$ (+1) In which version these functions were introduced? They aren't present in version 8.0.4. (Also you forgot to add the link in the last paragraph.) $\endgroup$ Commented Jul 2, 2017 at 9:24
  • $\begingroup$ I think in V10. I don't have access to all past versions, but they're in V10.4.1. $\endgroup$
    – Michael E2
    Commented Jul 2, 2017 at 17:06
16
$\begingroup$

This "replace" methods work only if there are no repeated rows (or columns if you will generalize) - see comments. For more general approach see @Szabolcs solution.

m = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
m // MatrixForm

enter image description here

Adding rows

m /. m[[2]] -> m[[2]] + m[[3]] // MatrixForm

enter image description here

Interchanging rows

m /. {m[[2]] -> m[[3]], m[[3]] -> m[[2]]} // MatrixForm

enter image description here

Multiplying row

m /. {m[[2]] -> 3 m[[2]]} // MatrixForm

enter image description here

Subtracting columns

Transpose@m /. {m[[All, 2]] -> m[[All, 2]] - m[[All, 1]]} 
//Transpose // MatrixForm

enter image description here

$\endgroup$
9
  • $\begingroup$ With adding rows, I mean adding the numbers of one row to an existing row $\endgroup$
    – sjdh
    Commented Mar 16, 2012 at 8:59
  • $\begingroup$ What if the matrix has two rows that are the same? The Replace approach will affect both. $\endgroup$
    – Szabolcs
    Commented Mar 16, 2012 at 9:09
  • $\begingroup$ @sjdh I see - added an example. $\endgroup$ Commented Mar 16, 2012 at 9:09
  • 4
    $\begingroup$ These ReplaceAll methods are dangerous because a matrix may contain repeated rows or columns. $\endgroup$
    – Mr.Wizard
    Commented Mar 16, 2012 at 9:10
  • $\begingroup$ @Szabolcs (and Mr.Wizard and nikie ;-) ) Very true - I'll add a comment at the top. $\endgroup$ Commented Mar 16, 2012 at 9:13
12
$\begingroup$

As matrix multiplication is highly optimized (see here), Dot and Inner (the general form of Dot) are often very efficient methods for column manipulation.

All of the following examples somewhere make use of Dot or Inner

Matrix and vector definition

(m = Array[Subscript[a, ##] &, {2, 3}]) // MatrixForm
 v = Table[Subscript[x, i], {i, 1, 3}]

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

$$\left\{x_1,x_2,x_3\right\}$$

Multiply a Matrix by a Vector

(See this SE question: Multiplying columns with factor)

Often it is not the dot product that is of interest,

m.v // MatrixForm

$$\left\{x_1 a_{1,1}+x_2 a_{1,2}+x_3 a_{1,3},x_1 a_{2,1}+x_2 a_{2,2}+x_3 a_{2,3}\right\}$$

but

(m.DiagonalMatrix[v])//MatrixForm

$$\left( \begin{array}{ccc} x_1 a_{1,1} & x_2 a_{1,2} & x_3 a_{1,3} \\ x_1 a_{2,1} & x_2 a_{2,2} & x_3 a_{2,3} \\ \end{array} \right)$$

Inner gives the same result:

Inner[Times, m, DiagonalMatrix[v]]

In the general form, Inner[f,list1,list2,g] , 'f plays the role of multiplication and g of addition' (Inner), and the result may also be obtained with:

Inner[Times, m, v, List]

That is:

m.DiagonalMatrix[v] == Inner[Times, m, DiagonalMatrix[v]] == Inner[Times, m, v, List]

 

Multiply a Column by a Factor

(See Change entire column of matrix using its own elements for calculations)

Multiply column-4 by 10

m.DiagonalMatrix[{1, 1, 10}] // MatrixForm

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

 

The diagonal matrix may be generated more efficiently with SparseArray. This gives the same result:

m.SparseArray[{{3, 3} -> 10, Band[{1, 1}] ->1}, Dimensions[m][[2]]]

Using Inner:

 Inner[Times, m, SparseArray[{{3, 3} -> 10, Band[{1, 1}] -> 1}, Dimensions[m][[2]]]]

or:

 Inner[Times, m, {1, 1, 10}, List]

 

Replace Column Entries with Zero

(see Replacing columns of a matrix with zeros)  

m.DiagonalMatrix[{1, 0, 0}] // MatrixForm

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

Alternatively:

Inner[Times, m, {1, 0, 0}, List] // MatrixForm

 

Add Column-3 to Column-1

m.SparseArray[{{3, 1} -> 1, Band[{1, 1}] -> 1}, Dimensions[m][[2]]] // MatrixForm

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

For clarity:

SparseArray[{{3, 1} -> 1, Band[{1, 1}] -> 1}, Dimensions[m][[2]]] // MatrixForm

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

 

Subtract Column-3 from Column-2

m // #.SparseArray[{{3, 2} -> -1, Band[{1, 1}] -> 1}, Dimensions[#][[2]]] & // MatrixForm

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

 

Subtract Column-1 from all other Columns

See the answer by Carl Woll to Subtracting elements in a nested list

m // #.(SparseArray[{Band[{1, 1}] -> 1, {1, _} -> -1}, Dimensions[#][[2]]]) & // MatrixForm

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

 

$\endgroup$
0
4
$\begingroup$

Applying functions to deeply nested matrices with AggregationLayer

AggregationLayer was introduced with V 11.1 and has received several updates since.

According to the Documentation it "aggregates an array of arbitrary rank into a vector", using any of the following functions:

Times, Total, Min, Max, Mean, Median, Variance, StandardDeviation, MeanDeviation and InterquartileRange.

m =
  {{{{10, 5, 10, 6}, {9, 8, 10, 5}, {9, 9, 2, 8}},
     {{10, 3, 1, 9}, {2, 7, 3, 4}, {7, 5, 6, 6}}}};

m // MatrixForm

enter image description here

All levels

AggregationLayer[Max, {1, 2, 3, 4}][m]

10.

Columns

AggregationLayer[Max, {1, 3}][m]

{{10., 9., 10., 8.}, {10., 7., 6., 9.}}

Rows

AggregationLayer[Max, {1, 4}][m]

{{10., 10., 9.}, {10., 7., 7.}}

Aggregated Columns

AggregationLayer[Max, {1, 2, 3}][m]

{10., 9., 10., 9.}

Aggregated Rows

AggregationLayer[Max, {1, 2, 4}][m]

{10., 10., 9.}

Submatrices

AggregationLayer[Min, {1, 3, 4}][m]

{2., 1.}

Submatrices per element

AggregationLayer[Min, {1, 2}][m]

{{10., 3., 1., 6.}, {2., 7., 3., 4.}, {7., 5., 2., 6.}}

$\endgroup$
1
  • $\begingroup$ It would be useful for users if you could add one or two lines of explanation for each command. It is difficult to understand the type of operations performed. $\endgroup$ Commented Oct 23, 2023 at 16:46
4
$\begingroup$
m = {{a, b, c}, {d, e, f}, {g, h, i}, {j, k, l}};

1. Threaded (since V 13.1)

Add a vector to each row:

m + Threaded[{u, v, w}] // MatrixForm

enter image description here

Multiply each row by a vector:

m * Threaded[{u, v, w}] // MatrixForm

enter image description here

2. Query

Apply a function to all elements of a column:

Query[All, {2 -> x}] @ m // MatrixForm

enter image description here

Apply functions to elements of several columns:

Query[All, {2 -> x, 3 -> y}] @ m // MatrixForm

enter image description here

3. ApplyTo (since V 12.2)

m =
 {{Pi/2, (3 Pi)/4, Pi, (5 Pi)/4},
  {(3 Pi)/4, Pi, (5 Pi)/4, (3 Pi)/2},
  {Pi, (5 Pi)/4, (3 Pi)/2, (7 Pi)/4},
  {(5 Pi)/4, (3 Pi)/2, (7 Pi)/4, 2 Pi}};

Apply Sin to 2nd matrix column and reset m to the result (from the documentation):

m[[All, 2]] //= Sin;

m // MatrixForm

enter image description here

4. ArrayReduce (since V 12.2)

Apply a function to all columns:

m = {{a, b, c}, {d, e, f}, {g, h, i}, {j, k, l}};

ArrayReduce[f, m, 1]

{f[{a, d, g, j}], f[{b, e, h, k}], f[{c, f, i, l}]}

5. CreateDataStructure (since V 12.1)

There are countless possibilities, for example:

ds = CreateDataStructure["LinkedList"];

Scan[ds["Append", #] &, m]

Swap rows 2 and 3

ds["SwapPart", 2, 3];

{{a, b, c}, {g, h, i}, {d, e, f}, {j, k, l}}

6. Partition

Partition[m, {2, 2}] // MatrixForm

enter image description here

$\endgroup$
2
  • $\begingroup$ CreateDataStructure looks very useful. Thanks for posting $\endgroup$
    – user1066
    Commented Nov 18, 2023 at 9:35
  • $\begingroup$ Exploring it is much fun - and once you have set up a structure, many operations are very fast $\endgroup$
    – eldo
    Commented Nov 18, 2023 at 9:37
3
$\begingroup$

Mapping across rows AND columns

list = Partition[Range[12], 3];

list // MatrixForm

enter image description here

Map[Accumulate, list, {0, 1}] // MatrixForm

enter image description here

Map[MovingAverage[#, 2] &, list, {0, 1}] // MatrixForm

enter image description here

$\endgroup$
2
$\begingroup$

Swapping rows and columns

m =
  {{"a", "b", "c"},
   {"d", "e", "f"},
   {"g", "h", "i"},
   {"j", "k", "l"}};

1. Rows

Swap rows 1 and 2

SubsetMap[RotateRight, m, {1, 2}] // MatrixForm

enter image description here

2. Columns

To swap columns we can use Query

Query[All, SubsetMap[RotateRight, #, {2, 3}] &] @ m // MatrixForm

or ArrayReduce (new in 12.2)

ArrayReduce[SubsetMap[RotateRight, #, {2, 3}] &, m, 2]

Both give

enter image description here

$\endgroup$
1
$\begingroup$

Apply functions with Query

1. Apply functions to row or column elements

1.1 Rows

m =
  {{"a", "b", "c"},
   {"d", "e", "f"},
   {"g", "h", "i"},
   {"j", "k", "l"}};

Apply one function to one row

Query[{2 -> Map[Boole @* LetterQ]}] @ m // MatrixForm

enter image description here

Apply two functions to two rows

Query[{2 -> Map[LetterQ], -1 -> Map[DigitQ]}] @ m // MatrixForm

enter image description here

1.2 Columns

Apply two functions to two columns

Query[All, {1 -> LetterQ, 3 -> DigitQ}] @ m // MatrixForm

enter image description here

2. Apply functions to entire rows or columns

2.1 Rows

Apply one function to one row

Query[{1 -> Reverse}] @ m // MatrixForm

enter image description here

Apply two functions to two rows

Query[{1 -> Reverse, 3 -> RotateRight}] @ m // MatrixForm

enter image description here

2.2 Columns

Apply one function to one column

Query[{1 -> Reverse}][m\[Transpose]]\[Transpose] // MatrixForm

enter image description here

Apply two functions to two columns

Query[{1 -> Reverse, 3 -> RotateRight}][m\[Transpose]]\[Transpose] // MatrixForm

enter image description here

$\endgroup$
1
$\begingroup$

Change rectangular blocks of matrix values

m = Array[0 &, {5, 4}];

Using MapAt

MapAt[1 &, {2 ;; 4, 3 ;; 4}] @ m // MatrixForm

enter image description here

Using SubsetMap (new in 12.0)

SubsetMap[{1, 2, 3, 4} &, m, Tuples[{2, 3}, 2]] // MatrixForm

enter image description here

SubsetMap[Range[6] &, m, Join @@ Table[{i, j}, {i, 2, 3}, {j, 3}]] // MatrixForm

enter image description here

$\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.