Mathematica:如何获取plot命令绘制的数据点?

Car*_*rey 13 wolfram-mathematica

当使用Plot绘制函数时,我想获得Plot命令绘制的数据点集.

例如,如何在以下简单示例中获取点的列表{t,f}?

f = Sin[t]
Plot[f, {t, 0, 10}]
Run Code Online (Sandbox Code Playgroud)

我尝试使用一种将值附加到列表的方法,如Jerry B. Keiper的Numerical1.ps(数学计算在Mathematica)第4页所示,http://library.wolfram.com/infocenter/Conferences/4687/ 如下:

f = Sin[t]
flist={}
Plot[f, {t, 0, 10}, AppendTo[flist,{t,f[t]}]]
Run Code Online (Sandbox Code Playgroud)

但无论我尝试什么,都会生成错误消息.

任何建议将不胜感激.

tom*_*omd 17

f = Sin[t];
plot = Plot[f, {t, 0, 10}]
Run Code Online (Sandbox Code Playgroud)

提取积分的一种方法如下:

points = Cases[
   Cases[InputForm[plot], Line[___], 
    Infinity], {_?NumericQ, _?NumericQ}, Infinity];
Run Code Online (Sandbox Code Playgroud)

ListPlot'看看'

ListPlot[points]
Run Code Online (Sandbox Code Playgroud)

给出以下内容:

在此输入图像描述

编辑 Brett Champion指出这InputForm是多余的.

ListPlot@Cases[
  Cases[plot, Line[___], Infinity], {_?NumericQ, _?NumericQ}, 
  Infinity]
Run Code Online (Sandbox Code Playgroud)

将工作.

也可以粘贴在绘图图形中,这有时很有用.例如,如果我创建一个外部数据的ListPlot然后错误地放置数据文件(这样我只能访问生成的图形),我可以通过选择图形单元格括号来重新生成数据,复制并粘贴:

ListPlot@Transpose[{Range[10], 4 Range[10]}]

points = Cases[
  Cases[** Paste_Grphic _Here **, Point[___], 
   Infinity], {_?NumericQ, _?NumericQ}, Infinity] 
Run Code Online (Sandbox Code Playgroud)

编辑2.

我也应该交叉引用并承认Yaroslav Bulatov的这个非常好的答案.

编辑3

Brett Champion不仅指出这FullForm是多余的,而且在GraphicsComplex生成a的情况下,应用Normal会将复合体转换为基元.这非常有用.

例如:

lp = ListPlot[Transpose[{Range[10], Range[10]}], 
  Filling -> Bottom]; Cases[
 Cases[Normal@lp, Point[___], 
  Infinity], {_?NumericQ, _?NumericQ}, Infinity] 
Run Code Online (Sandbox Code Playgroud)

给(正确)

{{1.,1.},{2.,2.},{3.,3.},{4.,4.},{5.,5.},{6.,6.},{ 7.,7.},{8.,8.},{9.,9.},{10.,10.}}

感谢Brett Champion.

最后,我在这里找到一个更简洁的方法来使用这个答案中给出的一般方法

就ListPlot而言,OP问题可以如下获得:

ListPlot@Cases[g, x_Line :> First@x, Infinity]
Run Code Online (Sandbox Code Playgroud)

编辑4

更简单

ListPlot@Cases[plot, Line[{x__}] -> x, Infinity]
Run Code Online (Sandbox Code Playgroud)

要么

ListPlot@Cases[** Paste_Grphic _Here **, Line[{x__}] -> x, Infinity]
Run Code Online (Sandbox Code Playgroud)

要么

ListPlot@plot[[1, 1, 3, 2, 1]]
Run Code Online (Sandbox Code Playgroud)

这评估为 True

plot[[1, 1, 3, 2, 1]] == Cases[plot, Line[{x__}] -> x, Infinity]
Run Code Online (Sandbox Code Playgroud)

  • `InputForm`是不必要的,但如果你无法控制情节的来源,你可以用`Normal`替换它.例如,如果添加"填充"选项,则绘图将包含"GraphicsComcplex",这些点将只是对全局点集的整数引用. (3认同)
  • `ListPlot [{1,2},Filling - > Bottom]`包含以下GraphicsComplex:`GraphicsComplex [{{1.,1.},{2.,2.},{1.,0.},{2 .,0.},{1.,1.},{2.,2.}},{{{},{},{},{},{指令[{Opacity [0.2],Hue [0.67, 0.6,0.6]}],行[{3,1}],行[{4,2}]}},{{},{Hue [0.67,0.6,0.6],Point [{5,6}]} ,{}}}]`.`Line [{4,2}]`意味着我们从第四点(`{2.,0.}`)到第二点(`{2.,2.}`)绘制一条线. (2认同)

Leo*_*rin 14

一种方法是使用EvaluationMonitor选项ReapSow,例如

In[4]:= 
(points = Reap[Plot[Sin[x],{x,0,4Pi},EvaluationMonitor:>Sow[{x,Sin[x]}]]][[2,1]])//Short

Out[4]//Short= {{2.56457*10^-7,2.56457*10^-7},<<699>>,{12.5621,-<<21>>}}
Run Code Online (Sandbox Code Playgroud)

  • 对于任何无法使用EvaluationMonitor的情况,您可以使用复合语句,例如:`{plot,{points}} = Reap [Plot [Sow [x]; Sin [x],{x,0,4 Pi}];`注意,在这种特殊情况下,前两个点应该被删除,因为它们不是数值评估循环的一部分. (4认同)

Sjo*_*ies 9

除了Leonid的答案和我的后续评论中提到的方法之外,为了实时跟踪缓慢函数的绘制进度以查看正在发生的事情,您可以执行以下操作(使用最近这个问题的示例):

(* CPU intensive function *)
LogNormalStableCDF[{alpha_, beta_, gamma_, sigma_, delta_}, x_] :=
 Block[{u},
  NExpectation[
   CDF[StableDistribution[alpha, beta, gamma, sigma], (x - delta)/u], 
   u \[Distributed] LogNormalDistribution[Log[gamma], sigma]]]

(* real time tracking of plot process *)
res = {};
ListLinePlot[res // Sort, Mesh -> All] // Dynamic

Plot[(AppendTo[res, {x, #}]; #) &@
  LogNormalStableCDF[{1.5, 1, 1, 0.5, 1}, x], {x, -4, 6}, 
 PlotRange -> All, PlotPoints -> 10, MaxRecursion -> 4]
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

在此输入图像描述

在此输入图像描述

等等


Ale*_*kov 6

这是获取所有数据点的一种非常有效的方法:

{plot, {points}} = Reap @ Plot[Last@Sow@{x, Sin[x]}, {x, 0, 4 Pi}]
Run Code Online (Sandbox Code Playgroud)

  • 或者,可以使Plot中的部分和赋值更清晰,代价是更精细的Reap语法:`{plot,points} = Reap [Plot [Sin @ x,x],{x,0 ,4 Pi}],_,{#,#2 [[1]]}&]` (2认同)