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