4
$\begingroup$

Say I have data which looks like data1 - this is "matrix" like data (is there a better descriptor?). The data looks like a matrix, and at each point in the matrix, it has a value. I can plot these in ListContourPlot and the like. e.g.

datafunction = MultinormalDistribution[{0, 0}, {{2, 1/2}, {1/2, 1}}];

(* matrix like data *) 

data1 = N[ Table[PDF[datafunction, {x, y}] /. {x -> xinsert, y -> yinsert}, {xinsert, -4, 4, 1}, {yinsert, -2, 2, 1}]];
ListContourPlot[data1]

enter image description here However, I can also create the same effect by making "coordinate" like data, where the data is a list of coordinates.

(* coordinate like data *) 

data2 = RandomVariate[MultinormalDistribution[{0, 0}, {{2, 1/2}, {1/2, 1}}], 1000];
ListPlot[data2]

enter image description here How would I convert data1 into data2? How do I convert matrix-like into coordinate-like?

I need to do some PCA analysis, I require the data to be in the form of individual points.

$\endgroup$
  • 3
    $\begingroup$ How do you think one could infer the individual counts from a total count? Once we have totaled data and thrown away the parts there is no way to reconstruct them. The mapping between sums and their constituents is not bijective. $\endgroup$ – Sjoerd C. de Vries Mar 9 at 16:36
6
$\begingroup$

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]

enter image description here

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 *)
$\endgroup$
4
$\begingroup$

An alternative approach based on Rescaleing 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

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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