11
$\begingroup$

Consider a table

tab = Table[{i,i^2,i^3,i^5,i^0.3,i^0.7},{i,0.2,3,0.1}];

I would like to multiply the 2rd and 5rd columns by some number. This is how I do it:

a = 2
{#[[1]],a*#[[2]],#[[3]],#[[4]],a*#[[5]],#[[6]]}&/@tab

However, such syntax becomes really annoying if the table would have many columns:

{...,a*#[[K]],...,a*#[[M]],...}&/@tab

where K,M are some numbers. How can I multiply the columns in a more compact way? I.e., what is an analog of ... in Mathematica?

$\endgroup$
0

6 Answers 6

17
$\begingroup$

The simplest method I can think off, is with Query:

Query[All, Thread[{2, 5} -> Function[a * #]]] @ tab
$\endgroup$
1
  • 2
    $\begingroup$ (+1, days ago!) It appears that in this case Query 'compiles' into a right-composition of the operator form of MapAt: Query[All, Thread[{2,5} -> Function[a * #]]]//Normal (* MapAt[a*#1 & , {All, 5}] /* MapAt[a*#1 & , {All, 2}] *) $\endgroup$
    – user1066
    Jun 10 at 14:06
18
$\begingroup$

Another option could be

a*tab[[All, {2, 5}]]

Which will multiply columns 2 and 5 by a. To replace the original matrix just do

tab[[All, {2, 5}]] = a*tab[[All, {2, 5}]];
$\endgroup$
2
  • 8
    $\begingroup$ also: tab[[All, {2, 5}]] *= a $\endgroup$
    – WReach
    Jun 8 at 14:33
  • $\begingroup$ easy for biginners $\endgroup$ Jun 14 at 23:04
9
$\begingroup$

Using the Dot product:

tab.DiagonalMatrix[{1,2,1,1,2,1}]

Or, if there are a lot of columns:

Edit

Lucas Lang suggested a neat modification, such as the following, to the original SparseArray answer (and thanks!):

tab.DiagonalMatrix[SparseArray[Thread[{2,5}->2], {6},1]]

Original answer

tab.SparseArray[{{2,2}->2, {5,5}-> 2,Band[{1, 1}] -> 1}, {6,6}]

With Inner:

Inner[Times, tab, {1,2,1,1,2,1}, List]

In addition, if the table consists of only two columns (a table of {x,y} values, maybe) and if it is desired to multiply all y-values by 2:

table.{{1,0},{0,2}}

For example:

tab[[All,;;2]].{{1,0},{0,2}}

Modify in place using ApplyTo (//=)

(modify tab, not a copy)

tab[[All,{2,5}]]//= 2#&

or using the new function syntax:

tab[[;;,{2,5}]]//=(x |-> 2 x)
$\endgroup$
1
  • 2
    $\begingroup$ You could also use a 1D SparseArray with default value 1, and then use DiagonalMatrix to convert it. That way you can avoid the 2D specifications and the need for Band $\endgroup$
    – Lukas Lang
    Jun 8 at 11:08
5
$\begingroup$
a = 2; k = 2; m = 5;

Using direct multiplication:

v = ReplacePart[ConstantArray[1, Last@Dimensions@tab], 
  List /@ {k, m} -> a]

{1, 2, 1, 1, 2, 1}

v tab[[#]] & /@ Range[Length@tab] // TableForm

Using MapAt:

MapAt[Times[a #] &, tab, {All, #} & /@ {k, m}] // TableForm

Using SubsetMap:

SubsetMap[Times[a #] &, tab[[#]], {k, m}] & /@ 
  Range[Length@tab] // TableForm
$\endgroup$
1
$\begingroup$
MapAt[a*#&,tab,{{All,2},{All,5}}]
$\endgroup$
1
$\begingroup$

Building a MultiplyByPosition function:

MultiplyByPosition[array_?VectorQ, factor_, positions : {___Integer}] := 
ReplacePart[array, Thread[Rule[Nest[Map[List, #] &, positions, 2], 
Flatten[factor*Extract[array, Nest[Map[List, #] &, positions, 2]]]]]]

MultiplyByPosition[array_?TensorQ, factor_, positions : {___Integer}] := 
Map[MultiplyByPosition[#, factor, positions] &, array]

Test:

array1 = {x1, x2, x3, x4, x5, x6};
array2 = {{x1, x2, x3, x4, x5, x6}, {y1, y2, y3, y4, y5, y6}};
MultiplyByPosition[array1, a, {1, 3, 5}]
(*{a x1, x2, a x3, x4, a x5, x6}*)
MultiplyByPosition[array2, a, {1, 3, 5}]
(*{{a x1, x2, a x3, x4, a x5, x6}, {a y1, y2, a y3, y4, a y5, y6}}*)
$\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.