2
$\begingroup$

I am aware that there are discussions here about multiplying rows or columns in matrices, but I cannot figure out what to do in the following two cases. I have a matrix, lets say

m = {{1, 2, 3, 4}, {0, 1, 2, 1}}

I want to multiply the last column by 2. What I tried was replace all. Particularly:

m2=m/.{m[[All, 4]] -> 2*m[[All, 4]]}

But unsuccessfully. If I write: m[[All, 4]] -> 2*m[[All, 4]] I get

{4, 1} -> {8, 2}

but if I use replaceAll (/.) it doesn't work. If I try to replace a row nevertheless it works fine, for example:

m3 = m /. {m[[2]] -> 2*m[[2]]}

Out:  {{1, 2, 3, 4}, {0, 2, 4, 2}}

What I need to do, is actually to replace the last column's elements with the ratio of the first element of each row over the sum of elements of 2nd column. I calculate the sum as

Total[m[[All, 2]]]

and I need somehow to create a new matrix that looks like this:

{{1,2,3,1/3},{0,1,2,0}}

But I don't know how to make the calculation, and repeat it for each row (since my original matrix, not provided in this naive approach has dozens of rows). Thank you in advance for your help.

$\endgroup$
7
  • 1
    $\begingroup$ Something like Replace[m, {b___, x_} -> {b, 2 x}, {1}] ? $\endgroup$ Commented Jul 28, 2016 at 15:04
  • 2
    $\begingroup$ m[[All, 4]] = 2 * m[[All, 4]] $\endgroup$
    – J_Nat
    Commented Jul 28, 2016 at 15:12
  • 1
    $\begingroup$ @J_Nat with your method all I have to do is write m[[All, 4]] = m[[All, 1]]/Total[m[[All, 2]]] . Interesting and amazingly obvious... $\endgroup$
    – Fierce82
    Commented Jul 28, 2016 at 15:18
  • 1
    $\begingroup$ @TomZinger Glad to be of service :) $\endgroup$
    – J_Nat
    Commented Jul 28, 2016 at 15:21
  • 3
    $\begingroup$ Why should this not be considered a duplicate of Elegant operations on matrix rows and columns? $\endgroup$
    – Jens
    Commented Jul 28, 2016 at 15:39

3 Answers 3

1
$\begingroup$

After the first evaluation is done, the Replace rule you're trying to apply is actually

{{1, 2, 3, 4}, {0, 1, 2, 1}} /. {  {4, 1} -> {8, 2}  }

The pattern {4, 1} never occurs in the input, so the rule has no effect. Rows, which do appear explicitly in the initial list, do get replaced.

In general, there's a huge number of ways to do what you're asking for, and it sort of depends on exactly where you want to go.

For example, if you just want to double up the last element of the list, then you can take a function that does that, like ({1,1,1,2} #)& (try it on {1,2,3,4}) and then Map it over your list, so

m = {{1, 2, 3, 4}, {0, 1, 2, 1}}
{1,1,1,2}# & /@ m

will do the trick, and it will probably be a very efficient way to get there.

To do the more complicated calculation, you can simply set total = Total[ m[[All,2]] ] and then map

{#[[1]], #[[2]], #[[3]], #[[1]]/total} & /@ m

(where now I need to explicitly build a list from the parts of #, and I need a precomputed total to avoid re-calculating it over and over).

$\endgroup$
2
  • 1
    $\begingroup$ Or use Append[Most[#], First[#]/total] &. $\endgroup$ Commented Jul 28, 2016 at 15:19
  • 1
    $\begingroup$ Yeah, you can rack up a bunch of equally nice ways for this. It's up to where the OP wants to go, really. $\endgroup$ Commented Jul 28, 2016 at 15:26
3
$\begingroup$

You can also use Span to achieve this m[[1 ;; 2, 4]] = m[[1 ;; 2, 1]]/Total[m[[1 ;; 2, 2]]]

$\endgroup$
1
  • 1
    $\begingroup$ Nice, clean, straight forward answer. Could also use m[[All,4]], etc rather than m[1;;2,4]. $\endgroup$ Commented Jul 29, 2016 at 2:08
2
$\begingroup$
mat = {{1, 2, 3, 4}, {0, 1, 2, 1}};

With[{sum = Total@mat[[All, 2]]},
 mat /. {a_, b__, _} :> {a, b, a/sum}]

Read on patterns and transformation rules in help.

$\endgroup$

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