У меня есть список дат и значений в формате:
{{{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, но я уверен, что многие из Вас чувствовали то же самое.
У вас есть список пар {дата, значение}, поэтому, если вы транспонируете , у вас будет список из двух списков - первый список дат и второй - список соответствующих значений. Затем вы можете взять Разницы значений, Вставить 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]]
За исключением того, что вам нужен начальный 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}}
Я рекомендую использовать 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!
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}
не совсем вписывается в последовательность, поэтому вы можете вручную добавить его в список