Как вычесть определенные элементы в списке с помощью функционального программирования в Mathematica?

У меня есть список дат и значений в формате:

{{{dateInfo1},value1},{{dateInfo2},value2},...,{{dateInfoN},valueN}}

С некоторыми фактическими датами и значениями:

{{{1971, 1, 31, 0, 0, 0.}, 1.0118}, {{1971, 2, 28, 0, 0, 0}, 1.0075},
 ..., {{2010, 5, 31, 0, 0, 0.}, 1.0403}}

Для любопытных, это - список США по сравнению со значениями $ CAD, которые вытягивают от базы данных FRED.

Я хотел бы просто вычесть value1 из значения 2 и затем создать новый список с данными в форме:

 {{{dateInfo1},0},{{dateInfo2},change1},...,{{dateInfoN},changeN-1}}

(причем change1 value2-value1),

Я знаю, что должен быть относительно простой способ сделать, это функциональное программирование использования, в противоположность Делают или В то время как с индексными переменными и подсчетом и всей той ерундой. Метод, который я пытаюсь выполнить, должен быть относительно устойчивым, потому что я автоматически вытягиваю в наборах данных из источников, которые имеют то же форматирование, но различные временные интервалы. Переграфическое изображение затем намного легче, если бы я не должен указывать интервалы даты ListPlot (который произошел бы, если бы я разделил dateInfo из списка).

Я знаком с Информационным центром и непрограммированием возможности Mathematica. Я изучал программирование с Mathematica, и действительно хочу расширить ту способность в функциональное программирование, но нашел большинство ресурсов по теме немного слишком трудным. Я чувствую, что я в том горбе в кривой обучения, где это собирается нажать в место, но прямо сейчас я борюсь. По крайней мере, если бы у Вас есть хороший источник на функциональном программировании, я был бы более, чем рад изучить их! Любая справка очень ценится! Извините, если это - TMI, но я уверен, что многие из Вас чувствовали то же самое.

6
задан Brian Tompsett - 汤莱恩 17 January 2016 в 23:16
поделиться

4 ответа

У вас есть список пар {дата, значение}, поэтому, если вы транспонируете , у вас будет список из двух списков - первый список дат и второй - список соответствующих значений. Затем вы можете взять Разницы значений, Вставить 0, а затем снова транспонировать, чтобы вернуться к списку пар.

В коде,

data = {{{1971,1,31,0,0,0}, 1.0118}, 
        {{1971,2,28,0,0,0}, 1.0075}, 
        {{2010,5,31,0,0,0}, 1.0403}}
{dates, values} = Transpose[data];
diffs = Prepend[Differences[values], 0];
answer = Transpose[{dates, diffs}]

который возвращает:

{{{1971,1,31,0,0,0}, 0}, 
 {{1971,2,28,0,0,0}, -0.0043}, 
 {{2010,5,31,0,0,0}, 0.0328}}

Чтобы объединить это в единую функцию, с благодарностью Янусу за идею:

taildiffs[data_]:= 
  Transpose @ {#1, Prepend[Differences[#2], 0]}& @@ Transpose@data  

Обратите внимание, что ... # 1 ... # 2 ...Конструкция & - это чистая функция:

http://reference.wolfram.com/mathematica/ref/Function.html

Синтаксис f @ x - это просто сокращение для ] f [x] .

Наконец, f @@ list является сокращением для Apply [f, list] :

http://reference.wolfram.com/mathematica/ref/Apply. html

Итак, taildiffs, как определено выше, является лишь краткой (возможно, загадочной) версией этого:

Apply[Transpose[Function[{x,y}, {x, Prepend[Differences[y],0]}], Transpose[data]]
7
ответ дан 8 December 2019 в 15:58
поделиться

За исключением того, что вам нужен начальный 0, вы ищете разности. Чтобы оставить даты в покое, транспонируйте и примените только ко второй части, например, так:

TailDifferences[data_]:=
  Transpose@Apply[{#1,{0}~Join~Differences[#2]}&,Transpose[data]]

Применив это к вашим данным, вы получите что-то вроде этого:

data={{{dateInfo1},value1},{{dateInfo2},value2},{{dateInfo3},value3}};
TailDifferences[data]

{{{dateInfo1},0},{{dateInfo2},-value1+value2},{{dateInfo3},-value2+value3}}
3
ответ дан 8 December 2019 в 15:58
поделиться

Я рекомендую использовать Reap и Sow для этого:

In[13]:= lis= {{{1971,1,31,0,0,0.},1.0118},{{1971,2,28,0,0,0},1.0075},{{2010,5,31,0,0,0.},1.0403}};

In[14]:= First@Last@Reap[
   (* set first previous to first value to get 0 *)
   Module[{prev = lis[[1, 2]]},
    Scan[
     (
       (* First[#] = date, Last[#] = value *)
       Sow[{First[#], Last[#] - prev}];
       (* set new previous to this value *)
       prev = Last[#]
       ) &,
     lis]]
   ]

Out[14]= {{{1971, 1, 31, 0, 0, 0.}, 0.},
  {{1971, 2, 28, 0, 0, 0}, -0.0043},
  {{2010, 5, 31, 0, 0, 0.}, 0.0328}}

Вывод Reap немного сложен, если вы не знакомы с ним, но Reap и Sow в основном дают вам способ «сеять» вещи в списки, а затем «пожинать» их после оценки. Reap и Sow намного эффективнее, чем, например, использование AppendTo со списком.

HTH!

2
ответ дан 8 December 2019 в 15:58
поделиться
data = {{{dateInfo1}, value1}, {{dateInfo2}, value2}, {{dateInfo3}, value3}}

Map[{#[[2,1]], #[[2,2]] - #[[1,2]]}&, {Take[data, Length[data] - 1], Rest[data]}]

дает

{{{dateInfo2}, -value1 + value2}, {{dateInfo3}, -value2 + value3}}

Этот первый элемент в вашем списке результатов

{{dateInfo1},0}

не совсем вписывается в последовательность, поэтому вы можете вручную добавить его в список

2
ответ дан 8 December 2019 в 15:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: