Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Mapping to a specific column or row in a matrix

31 views
Skip to first unread message

pfalloon

unread,
Sep 3, 2009, 7:10:15 AM9/3/09
to
Hi,
I'm wondering if there is a more simple/elegant way to Map a function
to a specific row or column of a matrix. The best I can come up
requires both Map and MapAt, but it feels like there should be
something more succinct (I suspect I may be overlooking something
obvious).

Example: suppose I want to divide entries in the 3rd column by 10.

(* my clunky solution *)
mat = ConstantArray[1, {10,5}];
res = Map[MapAt[#/10 &, #, 3] &, mat]


Note that the desired output is the entire matrix, so that rules out
something like:

mat[[All,3]]/10


One thing that would seem natural would be to allow "All" as an
element specification in the MapAt function. Thus, what I'm trying to
do would be expressed as:

(* doesn't work, but would be nice *)
MapAt[#/10 &, mat, {All,3}]

and if I wanted to do it to a specific row (say, the 3rd) it would be:

(* doesn't work, but would be nice *)
MapAt[#/10 &, mat, {3, All}]


Any thoughts/suggestions?

Thanks,
Peter.

Adriano Pascoletti

unread,
Sep 3, 2009, 7:54:43 PM9/3/09
to
2009/9/3 pfalloon <pfal...@gmail.com>

> Hi,
> I'm wondering if there is a more simple/elegant way to Map a function
> to a specific row or column of a matrix. The best I can come up
> requires both Map and MapAt, but it feels like there should be
> something more succinct (I suspect I may be overlooking something
> obvious).
>
> Example: suppose I want to divide entries in the 3rd column by 10.
>
> (* my clunky solution *)
> mat = ConstantArray[1, {10,5}];
> res = Map[MapAt[#/10 &, #, 3] &, mat]
>
>
> Note that the desired output is the entire matrix, so that rules out
> something like:
>
> mat[[All,3]]/10
>
>
> One thing that would seem natural would be to allow "All" as an
> element specification in the MapAt function. Thus, what I'm trying to
> do would be expressed as:
>
> (* doesn't work, but would be nice *)
> MapAt[#/10 &, mat, {All,3}]
>
>

mat.DiagonalMatrix[{1, 1, 1/10, 1, 1}]


MapAt[#/10 &, mat, {#, 3} & /@ Range@Length@mat]


Transpose[MapAt[#/10 &, Transpose@mat, {3}]]


> and if I wanted to do it to a specific row (say, the 3rd) it would be:
>
> (* doesn't work, but would be nice *)
> MapAt[#/10 &, mat, {3, All}]
>
>

> MapAt[#/10 &, mat, {3}]


Adriano Pascoletti

Any thoughts/suggestions?
>
> Thanks,
> Peter.
>
>

Vince

unread,
Sep 3, 2009, 7:56:32 PM9/3/09
to

Consider in-place modification, if you're working with a variable/
symbol:

mat = ConstantArray[1, {10,5}];

mat[[All,3]] /= 10;

or more generally:

mat[[All,3]] = op @ mat[[All, 3]];

where 'op' can of course be a function of more than its target.

Vince Virgilio

Leonid Shifrin

unread,
Sep 3, 2009, 7:56:42 PM9/3/09
to
Hi Peter,

I would define my own function:

In[1] =

ClearAll[mapAt,MappedListable];
Protect[MappedListable];
Options[mapAt] = {MappedListable -> False};
mapAt[f_, expr_, {pseq : (All | _Integer) ..}, OptionsPattern[]] :=
Module[{copy = expr},
copy[[pseq]] =
If[TrueQ[OptionValue[MappedListable]] && Head[expr] === List,
f[copy[[pseq]]],
f /@ copy[[pseq]]
];
copy];
mapAt[f_, expr_, poslist_List] := MapAt[f, expr, poslist];


This will do what you want:

In[2] =
mat = ConstantArray[1, {10, 5}];

In[3] = mapAt[#/10 &, mat, {All, 3}]

Out[3] =
{{1,1,1/10,1,1},{1,1,1/10,1,1},{1,1,1/10,1,1},{1,1,1/10,1,1},{1,1,1/10,1,1},{1,1,1/10,1,1},{1,1,1/10,1,1},{1,1,1/10,1,1},{1,1,1/10,1,1},{1,1,1/10,1,1}}

In[4] = mapAt[#/10 &, mat, {3, All}]

Out[4] =
{{1,1,1,1,1},{1,1,1,1,1},{1/10,1/10,1/10,1/10,1/10},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1}}

Also, it can take advantage of listability of some built-in functions:

In[5] = largemat = ConstantArray[1, {50000, 5}];

In[6] = mapAt[#/10 &, largemat, {All, 3}]; // Timing

Out[6] = {0.062, Null}

In[7] = mapAt[#/10 &, largemat, {All, 3}, MappedListable -> True]; // Timing

Out[7] = {0.016, Null}


Regards,
Leonid

Sseziwa Mukasa

unread,
Sep 3, 2009, 7:57:30 PM9/3/09
to

On Sep 3, 2009, at 7:10 AM, pfalloon wrote:

> Hi,
> I'm wondering if there is a more simple/elegant way to Map a function
> to a specific row or column of a matrix. The best I can come up
> requires both Map and MapAt, but it feels like there should be
> something more succinct (I suspect I may be overlooking something
> obvious).
>
> Example: suppose I want to divide entries in the 3rd column by 10.
>
> (* my clunky solution *)
> mat = ConstantArray[1, {10,5}];
> res = Map[MapAt[#/10 &, #, 3] &, mat]
>
>
> Note that the desired output is the entire matrix, so that rules out
> something like:
>
> mat[[All,3]]/10
>
>
> One thing that would seem natural would be to allow "All" as an
> element specification in the MapAt function. Thus, what I'm trying to
> do would be expressed as:
>
> (* doesn't work, but would be nice *)
> MapAt[#/10 &, mat, {All,3}]
>
> and if I wanted to do it to a specific row (say, the 3rd) it would be:
>
> (* doesn't work, but would be nice *)
> MapAt[#/10 &, mat, {3, All}]
>
>
> Any thoughts/suggestions?

I don't know if this is elegant, but you can specify all the
positions you want to operate on in a single MapAt expression:

operateOnColumn[mat_,col_,func_]:=MapAt[func,mat,{#,col}&/@Range[First
[Dimensions[mat]]]]
operateOnRow[mat_,row_,func_]:=MapAt[func,mat,{row,#}&/@Range[Last
[Dimensions[mat]]]]

Regards,

Ssezi

Valeri Astanoff

unread,
Sep 3, 2009, 7:57:40 PM9/3/09
to

Good day,

A double transpose seems to be slightly faster than map+mapat :

In[1]:= mat=ConstantArray[1,{1000,500}];

In[2]:= res=Map[MapAt[#/10&,#,300]&,mat]//Timing//Short
Out[2]//Short= {0.047,{<<1>>}}

In[3]:= res=(tm=Transpose[mat];tm[[300]]/=10;tm//Transpose)//Timing//
Short
Out[3]//Short= {0.031,{<<1>>}}

--
V.Astanoff

Ned Lieb

unread,
Sep 4, 2009, 3:13:09 AM9/4/09
to

Yep, there is. Double square brackets indicate coordinates.


To define a function as row x in a table defined as Table, for example, you'd write something like f=Table[[x]][All]]. I assume you can drop the same syntax into a mapping function.

------Original Message------

From: Vince

To: Mathgroup

Sent: Sep 3, 2009 7:56 PM

Subject: Re: Mapping to a specific column or row in a matrix

> Hi,

> obvious).

>

>

>

> something like:

>

> mat[[All,3]]/10

>

>

>

>

>

> Any thoughts/suggestions?

>

> Thanks,

> Peter.

Consider in-place modification, if you're working with a variable/

symbol:

mat = ConstantArray[1, {10,5}];

mat[[All,3]] /= 10;

dr DanW

unread,
Sep 10, 2009, 7:16:54 AM9/10/09
to
You are correct that you need a combination of Map and MapAt.
Specifically, you need the position spec from MapAt with the level
spec from Map.

MapAtLevel[f_, expr_, n_, levelspec_: {1}] :=
Map[MapAt[f, #, n] &, expr, levelspec - 1]

It looks like you did this, but called it clunky. By creating a new
function, it becomes much less clunky. I often have to plot data from
a list of {x,y} pairs, but I want to transform all the y values to
decibel:

dat = {{1, 200.}, {2, 250.}, {3, 300.}};

In[30]:= MapAtLevel[20 Log[10, #] &, dat, 2, 2]

Out[30]= {{1, 46.0206}, {2, 47.9588}, {3, 49.5424}}

Daniel

John Jowett

unread,
Sep 13, 2009, 8:01:20 AM9/13/09
to
Here are a few other methods which work:

I'm not sure why this method works. Perhaps someone can clarify?

mat = ConstantArray[1, {10, 5}];;
mat[[All, 3]] = mat[[All, 3]]/10;
mat

In this method (which I use a lot), the rule depends on the structure
and its contents

mat = ConstantArray[1, {10, 5}];

mat = mat /. {a_, b_, x_Integer, c__} :> {a, b, x/10, c}


This method feels safe but I don't like it and it may be inefficient:

mat = ConstantArray[1, {10, 5}];

Do[mat = ReplacePart[mat, {k, 3} -> mat[[k, 3]]/10], {k, 1, 10}];
mat

John Jowett

Leonid Shifrin

unread,
Sep 14, 2009, 7:11:46 AM9/14/09
to
Hi John,

On Sun, Sep 13, 2009 at 5:01 AM, John Jowett <john.m...@gmail.com>wrote:

> Here are a few other methods which work:
>
> I'm not sure why this method works. Perhaps someone can clarify?
>
> mat = ConstantArray[1, {10, 5}];;
> mat[[All, 3]] = mat[[All, 3]]/10;
> mat
>
>

Your code uses the special case of the extended functionality of Part, which
Vince and myself also used (somewhat more generally) in our posts earlier in
this thread. It works because <mat> is an L-value (can be modified
in-place), and because Part has this extended functionality to make multiple
assignments to regular (sub)structures simultaneously. The side effect of
execution of your code is that <mat> is modified. If this is not desirable,
one can use a local variable (like I did In my version),

Regards,
Leonid


> In this method (which I use a lot), the rule depends on the structure
> and its contents
>
> mat = ConstantArray[1, {10, 5}];
> mat = mat /. {a_, b_, x_Integer, c__} :> {a, b, x/10, c}
>
>
> This method feels safe but I don't like it and it may be inefficient:
>
> mat = ConstantArray[1, {10, 5}];
> Do[mat = ReplacePart[mat, {k, 3} -> mat[[k, 3]]/10], {k, 1, 10}];
> mat
>
> John Jowett
>
>
>
> On Sep 10, 1:16 pm, dr DanW <dmaxwar...@gmail.com> wrote:

0 new messages