5
$\begingroup$

I have an $N\times 2$ matrix $A = \begin{pmatrix} a_{11} & a_{12} \\ a_{21} & a_{22} \\ \vdots & \vdots \\ a_{N1} & a_{N2} \end{pmatrix}$. What is the cleanest code to make a new $N\times 2$ matrix $B$ with the first column unchanged but second column should consist of elements of second column of $A$ divided by the corresponding element of the first column of $A$. That is $a_{1i}$ divide by $a_{i1}$.

Thus the elements of $B$ should read

$B=\begin{pmatrix} a_{11} & a_{12}/a_{11} \\ a_{21} & a_{22}/a_{21} \\ \vdots & \vdots \\ a_{N1} & a_{N2}/a_{N1} \end{pmatrix}$

$\endgroup$
2
  • 4
    $\begingroup$ What about b = {#1, #2/#1} & @@@ a, clean enough? $\endgroup$
    – BlacKow
    Commented Sep 30, 2016 at 15:32
  • $\begingroup$ Woah. That's an answer. $\endgroup$ Commented Sep 30, 2016 at 15:35

6 Answers 6

13
$\begingroup$
(*matlab-like approach*)

nRows = 5;
nCols = 2;
(mat = Table[i + j, {i, nRows}, {j, nCols}]) // MatrixForm

Mathematica graphics

mat[[All, 2]] = mat[[All, 2]]/mat[[All, 1]];
mat // MatrixForm

Mathematica graphics

$\endgroup$
1
  • 2
    $\begingroup$ +1 Also: mat[[All, 2]] /= mat[[All, 1]] $\endgroup$
    – WReach
    Commented Sep 30, 2016 at 18:40
10
$\begingroup$

It's always nice to have a clean method, but if you have large matrix, performance can be an issue. Consider following comparison:

a = RandomReal[1, {1000000, 2}];
{t1, r1} = AbsoluteTiming[{#1, #2/#1} & @@@ a];
{t2, r2} = AbsoluteTiming[Transpose@{#1, #2/#1} & @@ Transpose@a];
{t1, t2, r1 == r2} 
(* {1.48458, 0.024882, True} *)

The first solution iterates over large index, it makes it way slower, although a little bit more cleaner visually.

$\endgroup$
1
  • $\begingroup$ Good demonstration! $\endgroup$ Commented Sep 30, 2016 at 16:19
2
$\begingroup$
a = {{2, 3}, {3, 4}, {4, 5}, {5, 6}, {6, 7}};

Using Cases

b = Cases[{a_, b_} :> {a, b/a}] @ a;

b // MatrixForm

enter image description here

If we want to change a inline we can use ApplyTo (new in 12.2)

a = {{2, 3}, {3, 4}, {4, 5}, {5, 6}, {6, 7}};

a //= Cases[{a_, b_} :> {a, b/a}];

a // MatrixForm

enter image description here

$\endgroup$
2
$\begingroup$
a = {{2, 3}, {3, 4}, {4, 5}, {5, 6}, {6, 7}};
MapThread[{#1,#2/#1}&,Transpose[a]]

(* {{2,3/2},{3,4/3},{4,5/4},{5,6/5},{6,7/6}} *)
$\endgroup$
2
$\begingroup$

Grabbing the @eldo's matrix and using SubsetMap:

a = {{2, 3}, {3, 4}, {4, 5}, {5, 6}, {6, 7}};

SubsetMap[#/a[[All, 1]] &, a, {All, 2}]

(*{{2, 3/2}, {3, 4/3}, {4, 5/4}, {5, 6/5}, {6, 7/6}}*)

Another faster solution is the following:

Thread@{#[[All, 1]], Divide @@ Transpose@#} &@a

(*{{2, 3/2}, {3, 4/3}, {4, 5/4}, {5, 6/5}, {6, 7/6}}*)
$\endgroup$
2
$\begingroup$
list = {{2, 3}, {3, 4}, {4, 5}, {5, 6}, {6, 7}};

Using ReverseApplied (new in 12.1)

With Cases

Cases[x_ :> {First @ x, ReverseApplied @ Divide @@ x}] @ list 

With Query

Query[All, {First, Apply @ ReverseApplied @ Divide}] @ list

With Comap (new in 14.0)

Comap[{First, Apply @ ReverseApplied @ Divide}] /@ list

All produce

{{2, 3/2}, {3, 4/3}, {4, 5/4}, {5, 6/5}, {6, 7/6}}

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