37
$\begingroup$

I need to save data that Mathematica uses inside the Plot command. The format that I would like to have is:

x1 y1
x2 y2
.....

i.e. basically, two columns, x and y (sorted, if possible) so that I can use the data for other programs.

I already played with Export and got the data enclosed in {} and tons of other information I don't need: color, axis, etc.

What is the nicest way to do what I am trying to do?

$\endgroup$
1
  • $\begingroup$ Related: (14222) $\endgroup$
    – Mr.Wizard
    Commented Jul 15, 2015 at 9:25

1 Answer 1

55
$\begingroup$

First you need to get the data from your Plot. Two methods are extraction with patterns:

data = Cases[Plot[Sin@x, {x, 0, 2 Pi}], Line[data_] :> data, -4, 1][[1]];

and EvaluationMonitor:

data =
 Reap[
   Plot[Sin@x, {x, 0, 2 Pi}, EvaluationMonitor :> Sow[{x, Sin@x}]]
 ][[2, 1]];

I prefer the first method's brevity and the fact that it can be used on existing Graphics output by Plot.

Then you just need to Export the data in the right format:

Export["file.txt", data, "Table"]

A somewhat more interesting example is saving data from a multi-line plot:

gr = Plot[{Sin@x, Cos@x, Sinc@x}, {x, 0, 2 Pi}]

Mathematica graphics

The expression assigned to gr is a Graphics object which has the form:

Graphics[primitives, options]

We are interested in the data that makes up the primitives, therefore we will operate on First @ gr. We will also not restrict the Cases to find only the first match as was done above (the fourth argument of Cases).

multidat = Cases[First @ gr, Line[data_] :> data, -4];

We could then export each part to a separate file like this:

Export["file" <> IntegerString[#2] <> ".txt", #, "Table"] & ~MapIndexed~ multidat
{"file1.txt", "file2.txt", "file3.txt"}

It should be pointed out that if you do not require the adaptive sampling of Plot you can generate your data more simply and directly using Table, e.g.:

Table[{x, Sin@x}, {x, 0, 2 Pi, 0.01}]

3D Plots

jheidk51 asks: "How can this be generalised for 3D plots?"

This depends on the format of the plot. In the simplest case of a single formal function (one z value per x,y pair) we can just pull all the points from GraphicsComplex:

gr3D = Plot3D[x^2*Cos[y], {x, -5, 5}, {y, -5, 5}];

points = FirstCase[p3D, GraphicsComplex[p_, __] :> p, {}, -4];

ListPlot3D[points]

enter image description here

However in plots with multiple surfaces the points will be mixed and jumbled. They are still valid points as shown with ListPointPlot3D but attempted surface plots will be a mess.

gr3Dmulti = 
 ParametricPlot3D[{{4 + (3 + Cos[v]) Sin[u], 4 + (3 + Cos[v]) Cos[u], 
    4 + Sin[v]}, {8 + (3 + Cos[v]) Cos[u], 3 + Sin[v], 
    4 + (3 + Cos[v]) Sin[u]}}, {u, 0, 2 Pi}, {v, 0, 2 Pi}, 
  PlotStyle -> {Red, Green}, Mesh -> None]

enter image description here

points = FirstCase[gr3Dmulti, GraphicsComplex[p_, __] :> p, {}, -4];

ListPointPlot3D[points, BoxRatios -> Automatic]

enter image description here

ListPlot3D[points, BoxRatios -> Automatic]

enter image description here

We can convert GraphicsComplex expressions to explicit coordinates using Normal, then split elements by GraphicsGroup and extract Polygon coordinates:

poly = 
   Cases[
      Normal[gr3Dmulti], 
      GraphicsGroup[g_] :>
         Cases[g, Polygon[p_, __] :> p, -4],
      -5
   ];

These polygon coordinates can be used to reconstruct the plot:

Graphics3D[{EdgeForm[], Orange, Polygon @ poly[[1]], Cyan, Polygon @ poly[[2]]}]

enter image description here

$\endgroup$
7
  • $\begingroup$ I had the same issue with NDSolve graph and I was looking for just 2 colums of pure numbers. This helped a lot. Thanks. $\endgroup$
    – ozmenc
    Commented Mar 24, 2013 at 13:01
  • $\begingroup$ I understand the use of levelspec -4, but puzzlingly, in the example the pattern allows this to work too: Cases[First@gr, Line[data_] :> data, -1] $\endgroup$ Commented Mar 25, 2013 at 10:47
  • $\begingroup$ @Chris Don't be puzzled. I normally use -1 with such patterns, but recently I've been trying to be more specific with my level specifications which in some cases makes a significant difference in speed as fewer expressions are scanned wastefully. In this case it doesn't make a big difference. $\endgroup$
    – Mr.Wizard
    Commented Mar 25, 2013 at 15:40
  • $\begingroup$ What are exactly these values Line[data_] :> data, -4, 1][[1]]; that are shown in mathematica??i have to extract values from a plot of a pretty complicated function and these informations are very important to me..thanks in advance! $\endgroup$
    – user30749
    Commented Jul 13, 2015 at 13:22
  • 1
    $\begingroup$ @jheidk51 I extended my answer to address this. Let me know if you have any problems or further questions. $\endgroup$
    – Mr.Wizard
    Commented Jul 16, 2020 at 15:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.