4
$\begingroup$

I have a list of data for which I need to multiply x-coordinates by 63 and y-coordinates by 50 inside the list. The list is in the following form:

a= {{x1,y1},{x2,y2},...,{xN,yN}} 

I want the result to look like as {{x1*63,y1*50},{x2*63,y2*50},...,{xN*63,yN*50}}. How could I do it?

$\endgroup$
  • 4
    $\begingroup$ A simple one-liner: Transpose[{63,50}*Transpose[a]] $\endgroup$ – KennyColnago May 17 '18 at 18:13
  • 1
    $\begingroup$ Thank you everyone for helping me, Now i could do it based on the ideas you posted above for my question $\endgroup$ – rabink May 17 '18 at 19:36
11
$\begingroup$

This should be fast, in particular if a is large packed array of reals ($\geq 1000000$ entries).

a.DiagonalMatrix[{63, 50}]
$\endgroup$
8
$\begingroup$

Since you are interested in large lists, I summarize below the efficiencies of all the methods proposed in the answers. From the faster to the slower:

a = RandomReal[{0, 1}, {5 10^5,2}];

AbsoluteTiming[a.DiagonalMatrix[{63, 50}]][[1]] (*0.003058*)

AbsoluteTiming[
  (a[[;; , 1]] = a[[;; , 1]]*63;
   a[[;; , 2]] = a[[;; , 2]]*50;)][[1]] (*0.041443*)

AbsoluteTiming[Transpose[{63, 50}*Transpose[a]]][[1]] (*0.008279*)

AbsoluteTiming[Function[x, {63 x[[1]], 50 x[[2]]}] /@ a][[1]] (*0.079297*)

AbsoluteTiming[(# {63, 50}) & /@ a][[1]] (*0.083761*)

AbsoluteTiming[ScalingTransform[{63, 50}]@a][[1]] (*0.102272*)

AbsoluteTiming[Thread[{63, 50}*Thread@a]][[1]] (*0.259768*)

f[{xi_, yi_}] := {63*xi, 50*yi}; AbsoluteTiming[Map[f, a]][[1]] (*0.900141*)

The method proposed by @Henrik Schumacher is by far the fastest!

$\endgroup$
  • $\begingroup$ BTW, I have no clue why the first one is so fast respect to the others! $\endgroup$ – Fraccalo May 17 '18 at 19:58
  • 2
    $\begingroup$ It's called vectorization. Modern CPUs employ fused multiply-add units that speed up vector-vector products (and thus also matrix-vector products) tremendously. Some implementations even perform a vector-product of two 4-vectors in on go. Moreover, the routines that Mathematica uses as backend for Dot (I'm talking about BLAS-rountines gemv and gemv) are highly optimized for the hardware on which you run the code. $\endgroup$ – Henrik Schumacher May 17 '18 at 20:09
  • 2
    $\begingroup$ The lesson to learn here: Always try to describe linear operations on big arrays by Dot. $\endgroup$ – Henrik Schumacher May 17 '18 at 20:14
  • 1
    $\begingroup$ Moreover: Albeit also vectorized, the second methods suffers from the fact that the array a is internally stored in this order: {a[[1,1]],a[[1,2]],a[[2,1]],a[[2,2]],a[[3,1]],...} So, the read operation a[[;; , 1]] rips this array apart and also the write operation does a[[;; , 1]]= ... not go into consecutive memory locations. Sometimes, it is better to transpose the array first, which leads to the third method. But it is also true that Transpose reorders. This should involve an unnecessary memory allocation and an unnecessary copy operation. $\endgroup$ – Henrik Schumacher May 17 '18 at 20:22
  • $\begingroup$ Amazing! Thanks A LOT for the explanation :D $\endgroup$ – Fraccalo May 17 '18 at 20:28
5
$\begingroup$
listOfPairs = {{1, 2}, {3, 4}};

(# {63,50})& /@ listOfPairs

{{63, 100}, {189, 200}}

Parentheses are here only for readibility

$\endgroup$
4
$\begingroup$

Just

a[[;; , 1]] = a[[;; , 1]]*63;
a[[;; , 2]] = a[[;; , 2]]*50;
$\endgroup$
  • $\begingroup$ Kiara, thanks for giving me idea. But the problem is, i had too many data inside the list. a1 = {{0.82, -109}, {0.98, -75}, {1.12, -57}, {1.17, -52}, {1.30, -43}, {1.37, -38}, {1.45, -34}, {1.54, -30}, {1.64, -26}, {1.76, -22.9}, {1.95, -18.6}, {2.06, -16.6}, {2.24, -13.8}, {2.47, -11.2}, {2.74, -8.9}, {3.09, -6.8}, {3.53, -5}, {3.80, -4.17}, {4.12, -3.4}, {4.59, -2.55}, {4.94, -2.06}, {5.26, -1.70}, {5.62, -1.37}, {5.83, -1.20}, {6.18, -0.96}, {6.51, -0.77}, {6.87, -0.58}}. How can it be done in a single thread with out separating the coordinates. $\endgroup$ – rabink May 17 '18 at 18:02
  • $\begingroup$ @rabink That redefines a, so the new a is what you seek. $\endgroup$ – corey979 May 17 '18 at 19:52
3
$\begingroup$

Also

ScalingTransform[{63, 50}]@a
$\endgroup$
1
$\begingroup$

Here is one way of doing this.

You could write a little function that accepts a list {xi,yi} and returns a list {63*xi,50*yi}. That function might look like

f[{xi_,yi_}]:={63*xi,50*yi}

Then you want to do that function to every item in your list a. Map will "do the same thing to every item in a list. That might look like

Map[f,a]

Let's see if it works

a={{1,2},{7,3},{5,1}};
f[{xi_,yi_}]:={63*xi,50*yi};
Map[f,a]

and the result is

{{63,100},{441,150},{315,50}}

Once you get the idea of how to do this you can then learn to translate this into cryptic punctuation and save typing a couple of characters each time. There are always a dozen ways of doing anything in Mathematica and some think the goal is to use the fewest possible characters to do anything. But for a new user the goal is to understand how to do things without making mistakes or misunderstanding.

$\endgroup$
  • $\begingroup$ great, it works. Thank you so much $\endgroup$ – rabink May 17 '18 at 18:08
0
$\begingroup$

Another way:

list = {{1, 2}, {3, 4}};
Function[x, {63 x[[1]], 50 x[[2]]}] /@ list


(*{{63, 100}, {189, 200}}*)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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