Related
I have drawn a figure with Mathematica, and want to read data from the figure. For example, there exists a Square Wave with the following code, and I want the value of the third turning point:
R[t_] := 10 UnitStep[-Sin[0.4 Pi t]];
Plot[R[t], {t, 0, 20}, Exclusions -> None, PlotStyle -> Thick]
yui = Flatten[Table[{t, (R[t] /. sol)}, {t, 5, 10, 1.2}]]
Partition[yui, 2] // TableForm
I make efford to read the value of the function wave. Due to the continuity of the curve, the value I read in this way may not be the right one.
Then, I use the command "Solve" with the following code:
Solve[R[t] = 5, {t, 5, 10, 1.2}]
But it does not work!
I really want to obtain the coordination, but with the wanted y value to get the exact x value.
Hence I need your help!
I tried this, but failed.
fig3D = ContourPlot3D[ x^2 + y^3 - z^2 == 0, {x, -2, 2}, {y, -2, 2}, {z, -2, 2},
PlotPoints -> 100]
pts = (InputForm#fig3D)[[1, 1, 1]];
ListSurfacePlot3D[pts]
The regenerated surface is very poor. Any suggestions? thanks!
Not too bad if you specify MaxPlotPoints
ListSurfacePlot3D[pts, Mesh -> None, MaxPlotPoints -> 100]
Compare with
ListSurfacePlot3D[pts]
Edit
Regarding the export to Excel, please consider that the Excel surface plot is a very basic construction and requires a matrix whose first file and column are the XY values with the Z values in the inner cells. Example:
So, exporting a working dataset to Excel may require (an unspecified amount of) data massaging.
How can I label each of these lines separately :
Plot[{{5 + 2 x}, {6 + x}}, {x, 0, 10}]
There's some nice code that allows you to do this dynamically in an answer to How to annotate multiple datasets in ListPlots.
There's also a LabelPlot command defined in the Technical Note Labeling Curves in Plots
Of course, if you don't have too many images to make,
then it's not hard to manually add the labels in using Epilog, for example
fns[x_] := {5 + 2 x, 6 + x};
len := Length[fns[x]];
Plot[Evaluate[fns[x]], {x, 0, 10},
Epilog -> Table[Inset[
Framed[DisplayForm[fns[x][[i]]], RoundingRadius -> 5],
{5, fns[5][[i]]}, Background -> White], {i, len}]]
In fact, you can do something similar with Locators that allows you to move the labels wherever you want:
DynamicModule[{pos = Table[{1, fns[1][[i]]}, {i, len}]},
LocatorPane[Dynamic[pos], Plot[Evaluate[fns[x]], {x, 0, 10}],
Appearance -> Table[Framed[Text#TraditionalForm[fns[x][[i]]],
RoundingRadius -> 5, Background -> White], {i, len}]]]
In the above I made the locators take the form of the labels, although it is also possible to keep an Epilog like that above and have invisible locators that control the positions.
The locators could also be constrained (using the 2nd argument of Dynamic) to the appropriate curves... but that's not really necessary.
As an example of the above code with the functions with the labels moved by hand:
fns[x_] := {Log[x], Exp[x], Sin[x], Cos[x]};
Mathematica 9 now provides easy ways to include legends.
Plot[{{5 + 2 x}, {6 + x}}, {x, 0, 10}, PlotLegends -> "Expressions"]
You can insert legends in your plot by loading the PlotLegends package
<<PlotLegends`;
Plot[{5+2 x,6+x},{x,0,10},
PlotLegend->{"5+2x","6+x"},LegendShadow->None,
LegendPosition->{0.3,-0.5},LegendSpacing->-0,LegendSize->0.5]
However, let me also note my dislike of this package, primarily because it's extremely counterintuitive, laden with too many options and does not provide a clean experience right out of the box like most of Mathematica's functions. You will have some fiddling around to do with the options to get what you want. However, in plots and charts where you do want a legend, this can be handy. Also see the comments to this answer and this question.
I am trying to prepare the best tools for efficient Data Analysis in Mathematica.
I have a approximately 300 Columns & 100 000 Rows.
What would be the best tricks to :
"Remove", "Extract" or simply "Consider" parts of the data structure, for plotting for e.g.
One of the trickiest examples I could think of is :
Given a data structure,
Extract Column 1 to 3, 6 to 9 as well as the last One for every lines where the value in Column 2 is equal to x and the value in column 8 is different than y
I also welcome any general advice on data manipulation.
For a generic manipulation of data in a table with named columns, I refer you to this solution of mine, for a similar question. For any particular case, it might be easier to write a function for Select manually. However, for many columns, and many different queries, chances to mess up indexes are high. Here is the modified solution from the mentioned post, which provides a more friendly syntax:
Clear[getIds];
getIds[table : {colNames_List, rows__List}] := {rows}[[All, 1]];
ClearAll[select, where];
SetAttributes[where, HoldAll];
select[cnames_List, from[table : {colNames_List, rows__List}], where[condition_]] :=
With[{colRules = Dispatch[ Thread[colNames -> Thread[Slot[Range[Length[colNames]]]]]],
indexRules = Dispatch[Thread[colNames -> Range[Length[colNames]]]]},
With[{selF = Apply[Function, Hold[condition] /. colRules]},
Select[{rows}, selF ## # &][[All, cnames /. indexRules]]]];
What happens here is that the function used in Select gets generated automatically from your specifications. For example (using #Yoda's example):
rows = Array[#1 #2 &, {5, 15}];
We need to define the column names (must be strings or symbols without values):
In[425]:=
colnames = "c" <> ToString[#] & /# Range[15]
Out[425]= {"c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "c10", "c11", "c12",
"c13", "c14", "c15"}
(in practice, usually names are more descriptive, of course). Here is the table then:
table = Prepend[rows, colnames];
Here is the select statement you need (I picked x = 4 and y=2):
select[{"c1", "c2", "c3", "c6", "c7", "c8", "c9", "c15"}, from[table],
where["c2" == 4 && "c8" != 2]]
{{2, 4, 6, 12, 14, 16, 18, 30}}
Now, for a single query, this may look like a complicated way to do this. But you can do many different queries, such as
In[468]:= select[{"c1", "c2", "c3"}, from[table], where[EvenQ["c2"] && "c10" > 10]]
Out[468]= {{2, 4, 6}, {3, 6, 9}, {4, 8, 12}, {5, 10, 15}}
and similar.
Of course, if there are specific correlations in your data, you might find a particular special-purpose algorithm which will be faster. The function above can be extended in many ways, to simplify common queries (include "all", etc), or to auto-compile the generated pure function (if possible).
EDIT
On a philosophical note, I am sure that many Mathematica users (myself included) found themselves from time to time writing similar code again and again. The fact that Mathematica has a concise syntax makes it often very easy to write for any particular case. However, as long as one works in some specific domain (like, for example, data manipulations in a table), the cost of repeating yourself will be high for many operations. What my example illustrates in a very simple setting is a one possible way out - create a Domain-Specific Language (DSL). For that, one generally needs to define a syntax/grammar for it, and write a compiler from it to Mathematica (to generate Mathematica code automatically). Now, the example above is a very primitive realization of this idea, but my point is that Mathematica is generally very well suited for DSL creation, which I think is a very powerful technique.
data = RandomInteger[{1, 20}, {40, 20}]
x = 5;
y = 8;
Select[data, (#[[2]] == x && #[[8]] != y &)][[All, {1, 2, 3, 6, 7, 8, 9, -1}]]
==> {{5, 5, 1, 4, 18, 6, 3, 5}, {10, 5, 15, 3, 15, 14, 2, 5}, {18, 5, 6, 7, 7, 19, 14, 6}}
Some useful commands to get pieces of matrices and list are Span (;;), Drop, Take, Select, Cases and more. See tutorial/GettingAndSettingPiecesOfMatrices and guide/PartsOfMatrices,
Part ([[...]]) in combination with ;; can be quite powerful. a[[All, 1;;-1;;2]], for instance, means take all rows and all odd columns (-1 having the usual meaning of counting from the end).
Select can be used to pick elements from a list (and remember a matrix is a list of lists), based on a logical function. It's twin brother is Cases which does selection based on a pattern. The function I used here is a 'pure' function, where # refers to the argument on which this function is applied (the elements of the list in this case). Since the elements are lists themselves (the rows of the matrix) I can refer to the columns by using the Part ([[..]]) function.
To pull out columns (or rows) you can do it by part indexing
data = Array[#1 #2 &, {5, 15}];
data[[All, Flatten#{Range#3, Range ## {6, 9}, -1}]]
MatrixForm#%
The last line is just to view it pretty.
As Sjoerd mentioned in his comment (and in the explanation in his answer), indexing a single range can be easily done with the Span (;;) command. If you are joining multiple disjoint ranges, using Flatten to combine the separate ranges created with Range is easier than entering them by hand.
I read:
Extract Column 1 to 3, 6 to 9 as well as the last One for every lines where the value in Column 2 is equal to x and the value in column 8 is different than y
as meaning that we want:
elements 1-3 and 6-9 from each row
AND
the last element from rows wherein [[2]] == x && [[8]] != y.
This is what I hacked together:
a = RandomInteger[5, {20, 10}]; (*define the array*)
x = 4; y = 0; (*define the test values*)
Join ## Range ### {1 ;; 3, 6 ;; 9}; (*define the column ranges*)
#2 == x && #8 != y & ### a; (*test the rows*)
Append[%%, #] & /# % /. {True -> -1, False :> Sequence[]}; (*complete the ranges according to the test*)
MapThread[Part, {a, %}] // TableForm (*extract and display*)
I have data in the form { {x,y,z,f}...} I am using ListContourPlot3D but all I get is an empty box with dimensions -1 to 1 in each direction. Here is my code:
ListContourPlot3D[data5, PlotRange -> All,
AxesLabel -> {"[Beta]", "[Omega]", "Vo"}, Contours -> {1500}].
These are the first 5 points of my data:( the whole set has 55 points)
{{200, 20000 10^(1/3), 2000, 1226},
{200, 20000 10^(1/3), 2600, 1422},
{200, 20000 10^(1/3), 3200, 1581},
{200, 20000 10^(1/3), 3800, 1761},
{200, 20000 10^(1/3), 4400, 1872}}
Dimensions[data5] returns {55,4}
If I do IntegerPart[data5] it does it correctly so it must recognize the numbers in my data.
I appreciate any ideas.
Thank you.
It's hard to tell without having the entire dataset, but I am betting there is a problem with your Contours -> {1500} setting. What happens if you omit it altogether or use a different value?
Contours -> num
Plots num equally spaced levels contours.
Contours -> {num}
Plots the f[x,y,z] = num contour.
Did you mean the former? I doubt ListContourPlot3D can plot your data if it is too sparse or to localized. For the data sample you gave us x and y do not vary at all. Does x and y vary enough in you final data set to well populate coordinate space?
#Davorak's suggestion that the data set, as written, does not seem to vary may be the cause of the problem. Assuming that is not the case, try rotating the resulting graphic, and if you see a black plane appear, then it is the color scheme that is off. By default, ListContourPlot3D produces an opaque white surface, and I've had issues where it did not seem to produce anything, but it was just invisible. The solution: add a ContourStyle option, and set it to something like Red.
The problem is using the {x,y,z,f} form of ListContourPlot3D at low resolution.
I stumbled over this a few weeks ago as well, here is a minimal example of the bug:
xyzfdata[r_] := Flatten[#, 2] &#Table[{x, y, z, x^2 + y^2 + z^2 - 1},
{x, -2, 2, r}, {y, -2, 2, r}, {z, -2, 2, r}];
(* Low resolution {x,y,z,f} fails *)
ListContourPlot3D[xyzfdata[1], Contours -> {0}]
The solution in my case (I had my data on a grid) was to use the grid form and DataRange:
fdata[r_] := Table[x^2 + y^2 + z^2 - 1,
{z, -2, 2, r}, {y, -2, 2, r}, {x, -2, 2, r}];
(* Low resolution works ok for array data *)
ListContourPlot3D[fdata[1], Contours -> {0},
DataRange -> 2 {{-1, 1}, {-1, 1}, {-1, 1}}]
I think the issue is that for the {x,y,z,f} form, the implementation uses interpolation in a way that fails at low resolution. Upping the resolution in the first example, everything works:
(* Higher resolution {x,y,z,f} works *)
ListContourPlot3D[xyzfdata[.2], Contours -> {0}]