Mathematica: Как получить данные, нанесенные командой plot?

При построении функции с использованием графика я хотел бы получить набор точек данных, построенных командой Plot.

Например, как я могу получить список точек {t, f}, используемый в следующем простом примере?

f = Sin[t]
Plot[f, {t, 0, 10}]

Я попытался использовать метод добавления значений в список, показанный на стр. 4 of Numerical1.ps(Численное вычисление в математике) Джерри Б. Кипером, http://library.wolfram.com/infocenter/Conferences/4687/ следующим образом:

f = Sin[t]
flist={}
Plot[f, {t, 0, 10}, AppendTo[flist,{t,f[t]}]]

но генерировать сообщения об ошибках независимо от того, что я пытаюсь.

Приветствуются любые предложения.

Ответы

Ответ 1

f = Sin[t];
plot = Plot[f, {t, 0, 10}]

Один способ извлечь точки выглядит следующим образом:

points = Cases[
   Cases[InputForm[plot], Line[___], 
    Infinity], {_?NumericQ, _?NumericQ}, Infinity];

ListPlot, чтобы "взглянуть"

ListPlot[points]

дает следующее:

enter image description here

ИЗМЕНИТЬ Бретт Чемпион указал, что InputForm является излишним.

[email protected][
  Cases[plot, Line[___], Infinity], {_?NumericQ, _?NumericQ}, 
  Infinity]

будет работать.

Также можно вставить графику сюжета, и это иногда полезно. Если, скажем, я создаю ListPlot внешних данных, а затем замаскирую файл данных (чтобы у меня был только доступ к сгенерированной графике), я могу регенерировать данные, выбирая графическую ячейку, скопируйте и вставьте:

[email protected][{Range[10], 4 Range[10]}]

points = Cases[
  Cases[** Paste_Grphic _Here **, Point[___], 
   Infinity], {_?NumericQ, _?NumericQ}, Infinity] 

Изменить 2.

Я также должен был перекрестно ссылаться и признавать этот очень приятный ответ Ярослава Булатова.

Изменить 3

Бретт Чемпион не только указал, что FullForm является излишним, но в тех случаях, когда генерируется a GraphicsComplex, применение Normal преобразует комплекс в примитивы. Это может быть очень полезно.

Например:

lp = ListPlot[Transpose[{Range[10], Range[10]}], 
  Filling -> Bottom]; Cases[
 Cases[[email protected], Point[___], 
  Infinity], {_?NumericQ, _?NumericQ}, Infinity] 

дает (правильно)

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

Спасибо Бретту Чемпиону.

Наконец, более простой способ использования общего подхода, данного в этом ответе, который я нашел здесь

Проблема OP в терминах ListPlot может быть получена следующим образом:

[email protected][g, x_Line :> [email protected], Infinity]

Изменить 4

Еще проще

[email protected][plot, Line[{x__}] -> x, Infinity]

или

[email protected][** Paste_Grphic _Here **, Line[{x__}] -> x, Infinity]

или

[email protected][[1, 1, 3, 2, 1]]

Это оценивается как True

plot[[1, 1, 3, 2, 1]] == Cases[plot, Line[{x__}] -> x, Infinity]

Ответ 2

Одним из способов является использование опции EvaluationMonitor с Reap и Sow, например

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

Ответ 3

В дополнение к методам, упомянутым в Ответу Леонида и моему комментарию, отслеживать ход выполнения медленных функций в режиме реального времени, чтобы узнать, что вы делаете следующее (используя пример этого недавнего вопроса):

(* 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]

enter image description here

enter image description here

enter image description here

и др.

Ответ 4

Вот очень эффективный способ получить все точки данных:

{plot, {points}} = Reap @ Plot[[email protected]@{x, Sin[x]}, {x, 0, 4 Pi}]

Ответ 5

Основываясь на ответе Sjoerd C. de Vries, я теперь написал следующий код, который автоматизирует предварительный просмотр сюжета (проверен на Mathematica 8):

pairs[x_, y_List]:={x, #}& /@ y
pairs[x_, y_]:={x, y}
condtranspose[x:{{_List ..}..}]:=Transpose @ x
condtranspose[x_]:=x
Protect[SaveData]
MonitorPlot[f_, range_, options: OptionsPattern[]]:=
  Module[{data={}, plot},
    Module[{tmp=#},
      If[FilterRules[{options},SaveData]!={},
        ReleaseHold[Hold[SaveData=condtranspose[data]]/.FilterRules[{options},SaveData]];tmp]]&@
    Monitor[Plot[(data=Union[data, {pairs[range[[1]], #]}]; #)& @ f, range,
                 Evaluate[FilterRules[{options}, Options[Plot]]]],
      plot=ListLinePlot[condtranspose[data], Mesh->All,
      FilterRules[{options}, Options[ListLinePlot]]];
      Show[plot, Module[{yrange=Options[plot, PlotRange][[1,2,2]]},
        Graphics[Line[{{range[[1]], yrange[[1]]}, {range[[1]], yrange[[2]]}}]]]]]]
SetAttributes[MonitorPlot, HoldAll]

В дополнение к отображению хода графика он также отмечает позицию x, в которой он рассчитывает.

Основная проблема заключается в том, что для нескольких графиков Mathematica применяет один и тот же сюжетный стиль для всех кривых на конечном графике (интересно, что это не на временных графиках).

Чтобы получить данные, полученные в переменной dest, используйте опцию SaveData:>dest

Ответ 6

Еще один способ, возможно, зависит от реализации:

[email protected][
            Plot[[email protected], {t, 0, 10}] /. Graphics[{{___, {_, y__}}}, ___] -> {y} /. Line -> List
         , 2]

enter image description here

Ответ 7

Просто загляните в структуру сюжета (для разных типов сюжетов будет немного другая структура) и используйте что-то вроде этого:

plt = Plot[Sin[x], {x, 0, 1}];
lstpoint = plt[[1, 1, 3, 2, 1]];