I often have a list of pairs, as
data = {{0,0.0},{1,12.4},{2,14.6},{3,25.1}}
and I want to do something, for instance Rescale
, to all of the second elements without touching the first elements. The neatest way I know is:
Transpose[MapAt[Rescale, Transpose[data], 2]]
There must be a way to do this without so much Transpose
ing. My wish is for something like this to work:
MapAt[Rescale, data, {All, 2}]
But my understanding is that MapAt
takes Position
-style specifications instead of Part
-style specifications. What's the proper solution?
I'm seeking a solution where I don't have to repeat myself, so lacking double Transpose
or double [[All,2]]
, because I consider repetition a signal I'm not doing something the easiest way. However, if eliminating the repetition requires the introduction of intermediate variables or a named function or other additional complexity, maybe the transpose/untranspose solution is already correct.
$Failed. Cell[BoxData["$Failed"], "Input", CellTags -> "$Failed_templates"] is a special symbol returned by certain functions when they cannot do what they were asked to do.
x≥y can be entered as x >= y or x \[GreaterEqual]y. GreaterEqual gives True or False when its arguments are real numbers. GreaterEqual does some simplification when its arguments are not numbers. For exact numeric quantities, GreaterEqual internally uses numerical approximations to establish numerical ordering.
Details. Flatten "unravels" lists, effectively just deleting inner braces. Flatten[list,n] effectively flattens the top level in list n times.
Use Part
:
data = {{0, 0.0}, {1, 12.4}, {2, 14.6}, {3, 25.1}}
data[[All, 2]] = Rescale @ data[[All, 2]];
data
Create a copy first if you need to. (data2 = data
then data2[[All, 2]]
etc.)
Amending my answer to keep up with ruebenko's, this can be made into a function also:
partReplace[dat_, func_, spec__] :=
Module[{a = dat},
a[[spec]] = func @ a[[spec]];
a
]
partReplace[data, Rescale, All, 2]
This is quite general is design.
I am coming late to the party, and what I will describe will differ very little with what @Mr. Wizard has, so it is best to consider this answer as a complementary to his solution. My partial excuses are that first, the function below packages things a bit differently and closer to the syntax of MapAt
itself, second, it is a bit more general and has an option to use with Listable
function, and third, I am reproducing my solution from the past Mathgroup thread for exactly this question, which is more than 2 years old, so I am not plagiarizing :)
So, here is the function:
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 is the same idea as what @Mr. Wizard used, with these differences: 1. In case when the spec is not of the prescribed form, regular MapAt
will be used automatically 2. Not all functions are Listable
. The solution of @Mr.Wizard assumes that either a function is Listable
or we want to apply it to the entire list. In the above code, you can specify this by the MappedListable
option.
I will also borrow a few examples from my answer in the above-mentioned thread:
In[18]:= mat=ConstantArray[1,{5,3}];
In[19]:= mapAt[#/10&,mat,{All,3}]
Out[19]= {{1,1,1/10},{1,1,1/10},{1,1,1/10},{1,1,1/10},{1,1,1/10}}
In[20]:= mapAt[#/10&,mat,{3,All}]
Out[20]= {{1,1,1},{1,1,1},{1/10,1/10,1/10},{1,1,1},{1,1,1}}
Testing on large lists shows that using Listability improves the performance, although not so dramatically here:
In[28]:= largemat=ConstantArray[1,{150000,15}];
In[29]:= mapAt[#/10&,largemat,{All,3}];//Timing
Out[29]= {0.203,Null}
In[30]:= mapAt[#/10&,largemat,{All,3},MappedListable->True];//Timing
Out[30]= {0.094,Null}
This is likely because for the above function (#/10&
), Map
(which is used internally in mapAt
for the MappedListable->False
(default) setting, was able to auto-compile. In the example below, the difference is more substantial:
ClearAll[f];
f[x_] := 2 x - 1;
In[54]:= mapAt[f,largemat,{All,3}];//Timing
Out[54]= {0.219,Null}
In[55]:= mapAt[f,largemat,{All,3},MappedListable->True];//Timing
Out[55]= {0.031,Null}
The point is that, while f
was not declared Listable
, we know that its body is built out of Listable
functions, and thus it can be applied to the entire list - but OTOH it can not be auto-compiled by Map
. Note that adding Listable
attribute to f
would have been completely wrong here and would destroy the purpose, leading to mapAt
being slow in both cases.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With