Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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}}
share|improve this question
    
add comment

6 Answers

up vote 12 down vote accepted

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}}
share|improve this answer
add comment
arr = {{1, 2}, {2, 4}, {2, 8}};
arr[[All,2]] *= 2;
share|improve this answer
    
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
add comment

I like to use Apply for this kind of task.

{#1, 2 #2} & @@@ {{1, 2}, {2, 4}, {2, 8}}
share|improve this answer
add comment

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.

share|improve this answer
4  
+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
add comment
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
*)
share|improve this answer
add comment

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)

share|improve this answer
1  
+1. You can also use {All, 2} in place of {1;;, 2} with MapAt –  RunnyKine Sep 15 '13 at 8:37
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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