如何在 Mathematica 中使用函数式编程减去列表中的特定元素?

发布于 2024-09-06 12:03:38 字数 973 浏览 6 评论 0原文

我有一个格式为以下的日期和值列表:

{{{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}}

对于那些好奇的人来说,这是从 FRED 数据库

我想简单地从值 2 中减去 value1,然后创建一个新列表,其数据格式如下:

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

(change1 为 value2-value1)

我知道一定有一种相对简单的方法可以使用函数式编程来完成此操作,而不是使用索引变量和计数以及所有这些废话来执行此操作。我试图实现的方法必须相对稳健,因为我会自动从具有相同格式但不同时间间隔的源中提取数据集。如果我不必指定 ListPlot 日期间隔(如果我从列表中删除 dateInfo 就会发生这种情况),那么重新绘制就会容易得多。

我熟悉文档中心和 Mathematica 非编程功能。我一直在使用 Mathematica 学习编程,并且真的想将这种能力扩展到函数式编程,但发现有关该主题的大多数资源都有点太困难了。我觉得我正处于学习曲线的驼峰上,即将步入正轨,但现在我正在挣扎。至少,如果您有关于函数式编程的良好资源,我会非常乐意研究这些!非常感谢任何帮助!抱歉,如果是 TMI,但我相信你们很多人也有同样的感觉。

I have a list of dates and values in the format:

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

With some actual dates and values:

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

For those curious, it's a list of US versus CAD $ values pulled from the FRED database.

I would like to simply subtract value1 from value 2, and then create a new list with data in the form of:

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

(with change1 being value2-value1)

I know there must be a relatively easy way to do this using functional programming, as opposed to Do or While with index variables and counting and all that nonsense. The method I'm trying to accomplish has to be relatively robust, because I am automatically pulling in datasets from sources that have the same formatting, but different time intervals. Replotting is then much easier if I don't have to specify the ListPlot date intervals (which would happen if I stripped the dateInfo from the list).

I am familiar with the Documentation Center and non-programming Mathematica capabilities. I have been learning programming with Mathematica, and really want to extend that ability into functional programming, but have found most of the resources on the topic a bit too difficult. I feel like I am at that hump in the learning curve where it's about to click into place, but right now I am struggling. At the very least if you have a good source on functional programming I would be more than happy to look into those! Any help is much appreciated! Sorry if it's TMI, but I'm sure many of you have felt the same way.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

葬花如无物 2024-09-13 12:03:38

您有一个 {date,value} 对列表,因此如果您转置您将得到一个包含两个列表的列表 - 第一个是日期列表,第二个是相应值的列表。
然后,您可以获取值的差异前置 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}}

将其包装到单个函数中,感谢 Janus 的想法:

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@@listApply[f, list] 的简写:

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

所以上面定义的 taildiffs 只是这个的简洁(也许是神秘的)版本:

Apply[Transpose[Function[{x,y}, {x, Prepend[Differences[y],0]}], Transpose[data]]

You have a list of {date,value} pairs so if you Transpose that you'll have a list of two lists -- the first a list of dates and the second a list of corresponding values.
You can then take the Differences of the values, Prepend 0, and then Transpose again to get back to a list of pairs.

In code,

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}]

which returns:

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

To wrap that up into a single function, with thanks to Janus for the idea:

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

Note that the ... #1 ... #2 ... & construct is a pure function:

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

The f@x syntax is simply shorthand for f[x].

Finally, f@@list is shorthand for Apply[f, list]:

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

So taildiffs as defined above is just a terse (perhaps cryptic) version of this:

Apply[Transpose[Function[{x,y}, {x, Prepend[Differences[y],0]}], Transpose[data]]
青巷忧颜 2024-09-13 12:03:38

除了您想要初始的 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}}

Except for the fact that you want the initial 0, you are looking for Differences. To leave the dates alone, transpose and apply to the second part only, like so:

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

Applying this to your data yields something like this:

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

{{{dateInfo1},0},{{dateInfo2},-value1+value2},{{dateInfo3},-value2+value3}}
李不 2024-09-13 12:03:38

我建议使用 ReapSow 为此:

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 会有点复杂,但是 ReapSow 基本上为您提供了一种将事物“播种”到列表中然后“收获”的方法评估后的他们。例如,ReapSow 比使用 AppendTo 和列表要高效得多。

哈!

I recommend using Reap and Sow for this:

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}}

The output of Reap is a little complicated if you aren't familiar with it, but Reap and Sow basically give you a way to "sow" things into lists and then "reap" them after the evaluation. Reap and Sow are much more efficient than using AppendTo with a list, for example.

HTH!

半透明的墙 2024-09-13 12:03:38
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}

并不真正适合序列,因此您可以手动将其添加到列表中

data = {{{dateInfo1}, value1}, {{dateInfo2}, value2}, {{dateInfo3}, value3}}

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

gives

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

This first element in your result list

{{dateInfo1},0}

doesn't really fit into the sequence, so you can manually prepend it to the list

漫雪独思 2024-09-13 12:03:38

此操作也可以使用 PartSet 完成:

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}};

Module[{a = data},
  a[[2 ;;, 2]] = Differences[a[[All, 2]]];
  a[[1, 2]] = 0;
  a
]
{{{1971, 1, 31, 0, 0, 0}, 0},
 {{1971, 2, 28, 0, 0, 0}, -0.0043},
 {{2010, 5, 31, 0, 0, 0}, 0.0328}}

This operation could also be done with Part and Set:

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}};

Module[{a = data},
  a[[2 ;;, 2]] = Differences[a[[All, 2]]];
  a[[1, 2]] = 0;
  a
]
{{{1971, 1, 31, 0, 0, 0}, 0},
 {{1971, 2, 28, 0, 0, 0}, -0.0043},
 {{2010, 5, 31, 0, 0, 0}, 0.0328}}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文