Arg*_*ens 10 wolfram-mathematica
我经常有一对配对列表,如
data = {{0,0.0},{1,12.4},{2,14.6},{3,25.1}}
Run Code Online (Sandbox Code Playgroud)
我想做一些事情,例如Rescale,对所有第二个元素做一些事情而不触及第一个元素.我知道的最好方法是:
Transpose[MapAt[Rescale, Transpose[data], 2]]
Run Code Online (Sandbox Code Playgroud)
必须有一种方法可以在没有这么多的情况下做到这一点Transpose.我的愿望是这样的事情起作用:
MapAt[Rescale, data, {All, 2}]
Run Code Online (Sandbox Code Playgroud)
但我的理解是MapAt采用Position风格规范而不是Part风格规范.什么是正确的解决方案?
我正在寻求一个解决方案,我不必重复自己,所以缺少双重Transpose或双重[[All,2]],因为我认为重复是一个信号,我没有做最简单的事情.但是,如果消除重复需要引入中间变量或命名函数或其他额外的复杂性,则转置/非转置解决方案可能已经正确.
Mr.*_*ard 10
用途Part:
data = {{0, 0.0}, {1, 12.4}, {2, 14.6}, {3, 25.1}}
data[[All, 2]] = Rescale @ data[[All, 2]];
data
Run Code Online (Sandbox Code Playgroud)
如果需要,首先创建一个副本.(data2 = data然后data2[[All, 2]]等)
修改我的答案跟上ruebenko的,这也可以变成一个函数:
partReplace[dat_, func_, spec__] :=
Module[{a = dat},
a[[spec]] = func @ a[[spec]];
a
]
partReplace[data, Rescale, All, 2]
Run Code Online (Sandbox Code Playgroud)
这是很普遍的设计.
我来晚会很晚了,我所描述的与@Mr的内容差异很小.向导有,所以最好将此答案视为对其解决方案的补充.我的部分借口是,首先,下面的函数包装的东西有点不同,更接近自己的语法MapAt,第二,它有点更通用,并有一个选项与Listable函数一起使用,第三,我正在复制我的解决方案过去Mathgroup主题正是这个问题,已经超过2年了,所以我不是在抄袭:)
所以,这是功能:
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];
Run Code Online (Sandbox Code Playgroud)
这与@Mr的想法相同.向导使用了这些差异:1.如果规范不是规定的形式,MapAt将自动使用常规2.并非所有功能都是Listable.@WhisWizard的解决方案假定函数是Listable或者我们想要将它应用于整个列表.在上面的代码中,您可以通过MappedListable选项指定.
我还将从上述帖子中的答案中借用几个例子:
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}}
Run Code Online (Sandbox Code Playgroud)
在大型列表上进行测试表明,使用可列表性可以提高性能,尽管这里没有那么显着:
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}
Run Code Online (Sandbox Code Playgroud)
这很可能是因为上面的函数(#/10&)Map(在内部mapAt用于MappedListable->False(默认)设置)能够自动编译.在下面的例子中,差异更大:
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}
Run Code Online (Sandbox Code Playgroud)
问题的关键是,虽然f是没有宣布Listable,我们知道它的机身内置了的Listable功能,因此它可以被应用到整个列表-但OTOH它不能自动编译Map.请注意,添加Listable属性f将在这里完全错误并且会破坏目的,导致mapAt两种情况都很慢.