# Multiplying two dimensional data by a constant

I have a list of lists of the form:

{{1, 2}, {2, 4}, {2, 8}}


But I want to multiply only the second dimension of that data by a constant. I know I could do this with a loop but that is "dirty". There has to be a better way. For example if I multiply the second dimension by 2 I would get:

{{1, 4}, {2, 8}, {2, 16}}

• smartThread[{{1, 2}, {2, 4}, {2, 8}}*{1, 2}] – ssch Sep 15 '13 at 9:59
• Transpose[{1, 2} Transpose[lst]] and ScalingTransform[{1, 2}][lst] are other possibilities. Both from an old MathGroup post by Carl Woll, according to my notes. The first one seems to be very fast. – user1066 Jan 29 '18 at 16:18

You can also do it this way:

{{1, 2}, {2, 4}, {2, 8}} /. {x_, y_} -> {x, 2 y}


Which gives:

{{1, 4}, {2, 8}, {2, 16}}


You can change 2 in 2 y to whatever constant you want. This method is flexible because, say you want to multiply the first dimension by a different constant you just put that number in front of x. E.g. Suppose you want to multiply the first dimension by 3 and the second by 2, you simply write:

 {{1, 2}, {2, 4}, {2, 8}} /. {x_, y_} -> {3 x, 2 y}


And this accomplishes the desired task.

EDIT: Using Pure Functions.

{#[[1]], 2 #[[2]]} & /@ {{1, 2}, {2, 4}, {2, 8}}

{First[#], 2 Last[#]} & /@ {{1, 2}, {2, 4}, {2, 8}}

arr = {{1, 2}, {2, 4}, {2, 8}};
arr[[All,2]] *= 2;

• Based on this principle I favor this answer. However, it should be noted that this modifies arr, so a copy should be modified if the original should be unchanged. – Mr.Wizard May 8 '13 at 2:13

I like to use Apply for this kind of task.

{#1, 2 #2} & @@@ {{1, 2}, {2, 4}, {2, 8}}


Works nicely:

{{1, 2}, {2, 4}, {2, 8}}.DiagonalMatrix[{1, 2}]


DiagonalMatrix[] is particularly convenient for scaling rows or columns.

From whuber:

Multiplying by a diagonal matrix is fast for up to somewhere between 100 and 1000 columns; beyond that, a solution modeled after Transpose[{1, 2} * Transpose[a]] becomes superior. Even better for such large matrices is a . SparseArray[Band[{1, 1}] -> {1, 2}]; this is superior to both once there are 20 columns or so.

• +1. Multiplying by a diagonal matrix is fast for up to somewhere between $100$ and $1000$ columns; beyond that, a solution modeled after Transpose[{1, 2} * Transpose[a]] becomes superior. Even better for such large matrices is a . SparseArray[Band[{1, 1}] -> {1,2}]; this is superior to both once there are $20$ columns or so. – whuber May 7 '13 at 22:06
• @whuber as J. M. made this post wiki please include that comment in the answer. – Mr.Wizard May 8 '13 at 2:14
Cases[{{1, 2}, {2, 4}, {2, 8}}, {x_, y_} -> {x, 2 y}]

Table[{First@i, Last@i*2}, {i, {{1, 2}, {2, 4}, {2, 8}}}]

{#1, 2 #2} & @@ Transpose@{{1, 2}, {2, 4}, {2, 8}} // Transpose

data = RandomReal[10, {10^6, 2}];
r1 = {#1, 2 #2} & @@ Transpose@data // Transpose; // Timing
r2 = {#1, 2 #2} & @@@ data; // Timing
r1 == r2
(*
{0.109201, Null}
{3.229221, Null}
True
*)


Here's another -general- approach, using MapAt. Maybe not the fastest, but I think it is pretty transparent and configurable:

MapAt[2 # &, list, {1 ;;, 2}]


or (thanks to @RunnyKine)

MapAt[2 # &, list, {All, 2}]


or interestingly, faster:

MapAt[(2 #) &, #, 2] & /@ list


Timings

Using data as in @chyanog's post, I get:

MapAt[2 # &, data, {1 ;;, 2}]; // Timing


{1.078534, Null}

MapAt[(2 #) &, #, 2] & /@ data; // Timing


{0.111480, Null}

(where my machine is about 2x faster than chyanog's, so his solution definitely is faster, by about factor 3) (and it doesn't make sense to compare to all the others, as e.g. DiagonalMatrix is suited for this task very well, but not as configurable)

• +1. You can also use {All, 2} in place of {1;;, 2} with MapAt – RunnyKine Sep 15 '13 at 8:37