5
$\begingroup$

A similar question regarding integer numbers was asked and answered here. However, since all the solutions there rely on generating the full set of numbers in the process of grouping them, which is not feasible in the case of floating point numbers, I'm asking the below question.

Consider a list of measurements {x,y} of some sorts, where x is a positive, monotonously increasing floating point number, for example:

list = {{1.1,2},{2.3,4},{4.5,5},{6.2,7},{8.3,8},{9.5,8}};

we also have a list of boundaries in x-space between which we would like to group the readings in list

boundaries = {1,5,7,10};

This particular list of boundaries tells us that we would like to group measurements in list for x-values between 1 and 5, between 5 and 7, and between 7 and 10. I would like to have a function group that does this:

group[list,boundaries]

{ {{1.1,2},{2.3,4},{4.5,5}} , {{6.2,7}} , {{8.3,8},{9.5,8}} }

Does Mathematica have such a function group, or maybe one can implement it efficiently? Of course, I could hack together a super ugly loop that would iterate through each element and append elements appropriately -- however, I'm wondering if there is a better, more efficient solution one could achieve through smarter Mathematica functions?

$\endgroup$

2 Answers 2

8
$\begingroup$

1. BinLists

grouP = Join @@ BinLists[#, {#2}, {{-∞, ∞}}] &;

grouP[list, boundaries]
 {{{1.1, 2}, {2.3, 4}, {4.5, 5}}, {{6.2, 7}}, {{8.3, 8}, {9.5, 8}}}

2. GatherBy

grouP2 = GatherBy[SortBy[First]@#, Function[x, Total[UnitStep[x[[1]] - #2]]]] &;

grouP2[list, boundaries]
 {{{1.1, 2}, {2.3, 4}, {4.5, 5}}, {{6.2, 7}}, {{8.3, 8}, {9.5, 8}}}

3. SplitBy

grouP3 = SplitBy[SortBy[First]@#, Function[x, Total[UnitStep[x[[1]] - #2]]]] &;

grouP3[list, boundaries]
 {{{1.1, 2}, {2.3, 4}, {4.5, 5}}, {{6.2, 7}}, {{8.3, 8}, {9.5, 8}}}

4. GroupBy

grouP4 = Values @ GroupBy[SortBy[First]@#, 
     Function[x, Total[UnitStep[x[[1]] - #2]]]] &;

grouP4[list, boundaries]
 {{{1.1, 2}, {2.3, 4}, {4.5, 5}}, {{6.2, 7}}, {{8.3, 8}, {9.5, 8}}}
$\endgroup$
1
  • $\begingroup$ Wow, especially amazed by the nice Join@@ instead of a probably way less efficient Flatten[#, 1] & /@! $\endgroup$
    – Kagaratsch
    Aug 23, 2020 at 19:28
1
$\begingroup$
Cases[list, {a_, b_} /; a > #1 && b <= #2] & @@@ Partition[boundaries, 2, 1]

{{{1.1, 2}, {2.3, 4}, {4.5, 5}}, {{6.2, 7}}, {{8.3, 8}, {9.5, 8}}}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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