在Mathematica中使用MapAt中的All

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)

这是很普遍的设计.


Leo*_*rin 5

我来晚会很晚了,我所描述的与@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两种情况都很慢.