Использование All в MapAt в Mathematica - PullRequest
10 голосов
/ 20 декабря 2011

У меня часто есть список пар, например

data = {{0,0.0},{1,12.4},{2,14.6},{3,25.1}}

, и я хочу сделать что-то, например Rescale, для всех вторых элементов, не касаясь первых элементов.Самый известный способ, который я знаю:

Transpose[MapAt[Rescale, Transpose[data], 2]]

Должен быть способ сделать это без такого большого количества Transpose инга.Я хочу, чтобы что-то вроде этого работало:

MapAt[Rescale, data, {All, 2}]

Но я понимаю, что MapAt принимает спецификации стиля Position вместо спецификаций стиля Part.Какое правильное решение?

Чтобы уточнить,

Я ищу решение, в котором мне не нужно повторяться, поэтому мне не хватает двойной Transpose или двойной [[All,2]], потому что яСчитайте повторение сигналом, я не делаю что-то проще всего.Однако, если устранение повторения требует введения промежуточных переменных или именованной функции или другой дополнительной сложности, возможно, решение для транспонирования / неперестановки уже является правильным.

Ответы [ 5 ]

10 голосов
/ 20 декабря 2011

Использование Part:

data = {{0, 0.0}, {1, 12.4}, {2, 14.6}, {3, 25.1}}

data[[All, 2]] = Rescale @ data[[All, 2]];

data

Сначала создайте копию, если вам нужно. (data2 = data, затем data2[[All, 2]] и т. Д.)


Изменение моего ответа, чтобы идти в ногу с ответом Рубенко, также может быть превращено в функцию:

partReplace[dat_, func_, spec__] :=
  Module[{a = dat},
    a[[spec]] = func @ a[[spec]];
    a
  ]

partReplace[data, Rescale, All, 2]

Это довольно общий дизайн.

5 голосов
/ 21 декабря 2011

Я опаздываю на вечеринку, и то, что я опишу, будет очень мало отличаться от того, что @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]; 

Это та же идея, что и @Mr. Используется мастер с такими отличиями: 1. В случае, если спецификация не имеет предписанной формы, автоматически будет использоваться обычный MapAt 2. Не все функции Listable. Решение @ Mr.Wizard предполагает, что либо функция имеет значение 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}}

Тестирование больших списков показывает, что использование Listability повышает производительность, хотя и не так резко:

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}

Вероятно, это связано с тем, что для вышеуказанной функции (#/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}

Дело в том, что в то время как f было не объявлено Listable, мы знаем , что его тело состоит из Listable функций, и, таким образом, оно может быть применяется ко всему списку - но OTOH он не может быть автоматически скомпилирован Map. Обратите внимание, что добавление атрибута Listable к f было бы совершенно неверным и разрушило бы цель, что привело к замедлению mapAt в обоих случаях.

3 голосов
/ 20 декабря 2011

Как насчет

Transpose[{#[[All, 1]], Rescale[#[[All, 2]]]} &@data]

, который возвращает то, что вы хотите (т. Е. Он не меняет data)

Если Transpose не разрешено,

Thread[Join[{#[[All, 1]], Rescale[#[[All, 2]]]} &@data]]

работает.

РЕДАКТИРОВАТЬ: поскольку цель «кратчайший» теперь является целью, лучше всего для меня пока это:

data\[LeftDoubleBracket]All, 2\[RightDoubleBracket] = Rescale[data[[All, 2]]]

на 80 символов, что идентично мистеру Уиздеру ... Так что голосуйте за его ответ .

2 голосов
/ 20 декабря 2011

Вот еще один подход:

op[data_List, fun_] := 
 Join[data[[All, {1}]], fun[data[[All, {2}]]], 2]

op[data, Rescale]

Редактировать 1 :

Расширение от Mr.Wizard, которое не копирует свои данные.

SetAttributes[partReplace, HoldFirst]
partReplace[dat_, func_, spec__] := dat[[spec]] = func[dat[[spec]]];

используется вот так

partReplace[data, Rescale, All, 2]

Редактировать 2 : или вот так

ReplacePart[data, {All, 2} -> Rescale[data[[All, 2]]]]
1 голос
/ 05 апреля 2012

Это сработало для меня и друга

In[128]:= m = {{x, sss, x}, {y, sss, y}}
Out[128]= {{2, sss, 2}, {y, sss, y}}

In[129]:= function[ins1_] := ToUpperCase[ins1];
fatmap[ins2_] := MapAt[function, ins2, 2];

In[131]:= Map[fatmap, m]
Out[131]= {{2, ToUpperCase[sss], 2}, {y, ToUpperCase[sss], y}}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...