5

How could I use BinLists to give elements indices in list instead of giving the list elements belonging to each bin ?

Thanks.

kglr
  • 394,356
  • 18
  • 477
  • 896
lagoa
  • 835
  • 1
  • 7
  • 10

3 Answers3

3

using the 2d form of BinLists ( note the first dimension binspec is cooked up so there is just one bin )

 list = RandomReal[{0, 1}, {20}];
 binspec = {0, 1, .1};
 (#[[All, 1]] & /@ First@BinLists[ MapIndexed[{First@#2, #} &, #] ,
       {0, Length@# + 1, Length@# + 1}, binspec]) &@list

{{1, 10, 20}, {6}, {7, 15}, {4}, {5, 12, 17}, {11}, {14, 18}, {9}, {2, 3, 8, 16, 19}, {13}}

 ( list[[#]] & /@ % ) == BinLists[ list , binspec] 

True

You could simply do this as well:

 Union@Flatten@(Position[ list, #]  & /@ # ) & /@ BinLists[list, binspec]
george2079
  • 38,913
  • 1
  • 43
  • 110
0

Using the function positionDuplicates from this answer by @Szabolcs

ClearAll[positionDuplicates, dispatchF, positionBins]
positionDuplicates[list_] :=  GatherBy[Range@Length[list], list[[#]] &]; 

dispatchF = Dispatch @ Thread[DeleteDuplicates[#] -> positionDuplicates[#]] &;
positionBins = Union @@@ (BinLists[#, #2] /. dispatchF[#1]) &;

Example 1:

data = RandomInteger[5, 17]

{5, 4, 1, 3, 0, 3, 0, 0, 5, 5, 0, 0, 5, 1, 5, 5, 0}

BinLists[data, 3] (* change `3` to your choice of binspecs *)

{{}, {1, 0, 0, 0, 0, 0, 1, 0}, {5, 4, 3, 3, 5, 5, 5, 5, 5}}

positionBins[data, 3]

{{}, {3, 5, 7, 8, 11, 12, 14, 17}, {1, 2, 4, 6, 9, 10, 13, 15, 16}}

Example 2:

BinLists[data, {{0, 2, 4, 6}}]

{{1, 0, 0, 0, 0, 0, 1, 0}, {3, 3}, {5, 4, 5, 5, 5, 5, 5}}

positionBins[data, {{0, 2, 4, 6}}]

{{3, 5, 7, 8, 11, 12, 14, 17}, {4, 6}, {1, 2, 9, 10, 13, 15, 16}}

kglr
  • 394,356
  • 18
  • 477
  • 896
0

For my own question and self-answer I wrote the following utility function.

BinPositions[vals_, brakes_, sameTest_] :=
 Map[val \[Function] 
   Catch@Module[{lo = 1, mid, hi = Length[brakes], el, res},
     While[lo <= hi, Which[
       TrueQ@sameTest[val, el = brakes[[mid = Floor[(lo + hi)/2]]]], 
       Throw[mid],
       el > val, hi = mid - 1,
       True, lo = mid + 1]];
     lo - 1/2],
  vals]

The semanthic is sligtly different from previous answer, but, maybe, it can be adapted to your scenario.

list = RandomReal[{0, 100}, {20}]
brakes = Union@RandomInteger[{0, 100}, 10]
Floor@BinPositions[list, brakes, SameQ]

{48.311, 40.7217, 50.8321, 73.2729, 24.7769, 42.4868, 12.475, 7.04288, 3.22704, 89.9731, 82.0066, 73.565, 83.0642, 45.4985, 81.3878, 55.5902, 82.3677, 68.8531, 57.4473, 83.1311}

{6, 20, 28, 32, 35, 52, 73, 82, 95}

{5, 5, 5, 7, 2, 5, 1, 1, 0, 8, 8, 7, 8, 5, 7, 6, 8, 6, 6, 8}

unlikely
  • 7,103
  • 20
  • 52