Converting from "matrix" data into "coordinate" data
The reshaping can be done in several ways. Below are given three using SparseArray
,
"SSparseMatrix.m"
, and "DataReshape.m"
. (The first one is/was the accepted answer.)
I do these kind of transformations often while using sparse matrices (with named rows and columns) and Dataset
objects. So, this answer is a good place to mention the related packages.
Data generation
First generating the data (simpler than in the question):
datafunction = MultinormalDistribution[{0, 0}, {{2, 1/2}, {1/2, 1}}];
data1 = N[Table[PDF[datafunction][{x, y}], {x, -4, 4, 1}, {y, -2, 2, 1}]];
MatrixForm[data1]
First answer (no-packages)
Make index-to-value associations corresponding to the ranges used to make data1
:
aX = AssociationThread[Range[Length[#]], #] &@Range[-4, 4, 1];
aY = AssociationThread[Range[Length[#]], #] &@Range[-2, 2, 1];
Convert to a sparse array, take the corresponding rules, and map the {x,y}
indexes to the actual x's and y's.
arules = Most[ArrayRules[SparseArray[data1]]];
data2 = Map[{aX[#[[1, 1]]], aY[#[[1, 2]]], #[[2]]} &, arules]
Plot (note the axes ticks):
ListContourPlot[data2]
Alternative answer using "SSparseMatrix.m"
This answer is just a package-based version of the previous one.
Import["https://raw.githubusercontent.com/antononcube/\
MathematicaForPrediction/master/SSparseMatrix.m"]
smat1 = ToSSparseMatrix[SparseArray[data1],
"RowNames" -> Map[ToString, Range[-4, 4, 1]],
"ColumnNames" -> Map[ToString, Range[-2, 2, 1]]]
data2a = SSparseMatrixToTriplets[smat1];
data2a = data2a /. x_String :> ToExpression[x];
data2a == data2
(* True *)
Alternative answer with "DataReshape.m"
The package "DataReshape.m" was made because I have to often convert tabular data (Dataset
objects) from "wide form" to "long form" and vice versa. (For R there are at least two dedicated packages from RStudio for doing these kind of transformations.)
Import["https://raw.githubusercontent.com/antononcube/\
MathematicaForPrediction/master/DataReshape.m"]
ds1 = Dataset[
AssociationThread[Range[-4, 4, 1],
AssociationThread[Range[-2, 2, 1], #] & /@ data1]];
?ToLongForm
(* ToLongForm[ds_Dataset, idColumns_, valueColumns_] converts the \
dataset ds into long form. The resulting dataset has the columns \
idColumns and the columns "Variable" and "Value" derived from \
valueColumns. *)
data2b = Normal[ToLongForm[ds1][Values]];
data2b == data2
(* True *)
An alternative approach based on Rescale
ing the "NonzeroPositions"
of SparseArray[data1]
:
xrange = {-4, 4};
yrange = {-2, 2};
sa = SparseArray[data1];
nzp = sa["NonzeroPositions"];
nzv = sa["NonzeroValues"];
data2b = Join[Transpose[Rescale[#, MinMax@#, #2] & @@@
Thread[ {Transpose@nzp, {xrange, yrange}}]], List /@ nzv, 2];
data2b == data2 (* from Anton's answer *)
True