3
$\begingroup$

Consider the following table:

grid1 = {0.1, 0.2, 0.2, 0.3, 0.4, 0.5};
grid2 = {0.2, 0.3, 0.7, 0.8, 1.1, 1.2};
grid3 = {0.17, 0.25, 0.35, 0.35, 0.4};
tuples = Join[Tuples[{grid1, grid2, grid3}],RandomReal[{1, 2}, {6*6*5, 1}],2];

I do not have grid1, grid2, grid3, only the resulting tuples, but I want to find them. If they did not contain duplicating points, it would be, e.g., simply

grid1 = DeleteDuplicates[tuples[[All,1]]]

but it would remove the extra 0.2 and make things wrong:

{0.1, 0.2, 0.3, 0.4, 0.5}

Is there any quick approach to the extraction of these grids?

Actually, I simply need to find the duplicates in each of the grids.

Edit

An ugly way would be like this:

grid1 = tuples[[All, 1]] // DeleteDuplicates
tableoccurences=Table[Length[Select[tuples, #[[1]] == grid1[[i]] &]], {i, 1, Length[grid1], 1}]
occmin = tableoccurences // Min
grid1 = Table[
   Table[grid1[[i]], tableoccurences[[i]]/occmin], {i, 1, 
    Length[grid1], 1}] // Flatten

and so on. tableoccurences counts the number of times each element of the grid is present in tuples. The main problem is that the approach assumes that occmin corresponds to the element that is present only once.

$\endgroup$
3
  • 1
    $\begingroup$ Do you know the lengths 6, 6, and 5 before-hand, or does this need to be inferred from the structure of tuples? And can you clarify what "Actually, I simply need to find the duplicates in each of the grids." means? $\endgroup$
    – march
    Feb 2 at 16:48
  • $\begingroup$ @march : it is unknown. $\endgroup$ Feb 2 at 20:45
  • $\begingroup$ @march : I needed to find what element is present more than one time. $\endgroup$ Feb 2 at 22:57

2 Answers 2

4
$\begingroup$

If we know that tuples is constructed from ngrids input grids and if each grid has at least one non-repeating element, we can get the duplicates and their counts in each of the grids using

extractDuplicates = 
  Map[l |-> Select[GreaterThan[1]] @ Normalize[#, Min] & @ Counts[#[[All,l]]]] @
  Range @ #2 &;

ngrids = 3;

extractDuplicates[tuples, ngrids]
 {<|0.2 -> 2|>, <||>, <|0.35 -> 2|>}

We can get the input grids and their lengths as follows:

extractGridLengths = 
  Map[l |-> Length @ # / Min @ Counts[#[[All, l]]]] @ Range @ #2 &;

extractGridLengths[tuples, ngrids]
{6, 6, 5}

To get grid1, grid2 and grid3, we can use a combination of ArrayReshape and Extract to get the grids:

extractGridPositions = 
  Extract @ 
  Map[m |-> {Splice @ ReplacePart[Table[1, #], {m} -> All], m}] @
  Range[#] &;

extractGrids = extractGridPositions[#2] @
    ArrayReshape[#, 
     Append[Length @ First @ #]@ extractGridLengths[#, #2]] &;

extractGrids[tuples, ngrids] == {grid1, grid2, grid3}
True

Another example:

SeedRandom[1];

numberOfGrids = RandomInteger[{2, 9}]
8
randomGridLength := RandomInteger[{1, 8}]

randomGrids = Table[
 While[Min@Counts[$g = RandomInteger[3, randomGridLength]] > 1]; $g, 
 numberOfGrids]
{{2, 0, 0, 0},   
 {0, 1, 2},   
 {1},   
 {0, 2, 3, 3, 3}, 
 {3, 2, 0, 1, 3, 3, 0}, 
 {0, 2, 1},   
 {2, 3, 0, 2, 2},   
 {3}}
Map[Length] @ randomGrids
  {4, 3, 1, 5, 7, 3, 5, 1}
randomPadding = RandomReal[{1, 2}, {Times @@ Map[Length] @ randomGrids, 1}];

randomTuples = Join[Tuples@randomGrids, randomPadding, 2];


randomTuples // RandomSample[#, 10] & // Column

enter image description here

extractGridLengths[randomTuples, numberOfGrids]
 {4, 3, 1, 5, 7, 3, 5, 1}
extractDuplicates[randomTuples, numberOfGrids]
 {<|0 -> 3|>, <||>, <||>, <|3 -> 3|>,   
  <|3 -> 3,  0 -> 2|>, <||>, <|2 -> 3|>, <||>}
extractGrids[randomTuples, numberOfGrids] == randomGrids
True
$\endgroup$
1
  • $\begingroup$ Fantastic, thanks! $\endgroup$ Feb 2 at 22:57
4
$\begingroup$

If you know the lengths Length@grid1 == 6, Length@grid2 == 6, Length@grid3 == 5, then you can take advantage of the structure of Tuples to brute force this:

grid1 = {0.1, 0.2, 0.2, 0.3, 0.4, 0.5};
grid2 = {0.2, 0.3, 0.7, 0.8, 1.1, 1.2};
grid3 = {0.17, 0.25, 0.35, 0.35, 0.4};
tuples = Join[Tuples[{grid1, grid2, grid3}],RandomReal[{1, 2}, {6*6*5, 1}],2];

tuples[[;; ;; Length@grid2 Length@grid3, 1]]
tuples[[;; Length@grid2 Length@grid3 ;; Length@grid3, 2]]
tuples[[;; Length@grid3, 3]]

will result in the three grid lists.

$\endgroup$

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.