TransWikia.com

How to do two different kinds of binning for a given list of elements?

Mathematica Asked by kosif on February 22, 2021

I have a long list consists of float numbers with some of them duplicated as shown below.

list output

I want to divide this list into bins;

  1. with equal bin width so that in each bin there might be one or more than one member, even duplicated numbers come from the main list.
  2. with variable bin width so that in each bin there will be the same amount of members.

For the first item, I start with deciding on a binning amount and find suitable bin width (in this case 0.001) for this binning amount as below;

binningamount = 996;
min = Floor[Min[DeleteCases[Sort[DeleteDuplicates[list]], "NA"]], 0.1]
max = Ceiling[Max[DeleteCases[Sort[DeleteDuplicates[list]], "NA"]]]
Length[DeleteCases[BinLists[list, {min, max, 0.001}], {}]] == binningamount

and create binned list as below;

binning = 
  Table[Catch[
    Do[If[IntervalMemberQ[Interval[i], list[[j]]] == True, Throw[i]],
     {i, Partition[Range[min, max, 0.001], 2, 1]}]], {j, Length[list]}];

Output:
output for binned list

I am wondering,

  • Is there a way to perform the first item easier than I showed above? For instance, giving the binning amount and get suitable bin width value to apply to list.
  • How is it possible to achieve the second item?

2 Answers

binamount is equal:

binamount == Floor[(max - min)/binwidth]

Therefore binwidth lies in this interval:

(max - min)/(binamount + 1) < binwidth <= (max - min)/binamount

So for your original list:

list = {1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 8, 8, 9, 10, 10, 11, 12, 12, 12,
    12, 12, 12, 12, 13, 14, 15, 16};
{min, max} = MinMax[list];

If you want, for example, binamount==7 you can choose binwidth value from the following interval:

(max - min)/(binamount + 1) < binwidth <= (max - min)/binamount /. 
  binamount -> 7 // N
(*1.875 < binwidth <= 2.14286*)

Answered by azerbajdzan on February 22, 2021

Regarding the first goal item, modifying the answer belongs to @azerbajdzan, I came up with a function that generates binning with the arguments; list itself and requested bin amount.

    binner[list_, binamount_] := 
 Module[{min, max, maxwidth, binnedlist, binamountcheck, result},
  min = Min[list];
  max = Max[list] + 1;
  maxwidth = (max - min)/binamount;
  binnedlist = BinLists[list, {min, max, maxwidth}];
  binamountcheck = Length[DeleteCases[binnedlist, {}]];
  result = 
   If[binamountcheck == binamount, binnedlist, 
    DeleteCases[binnedlist, {}] -> 
     Row[{Length[DeleteCases[binnedlist, {}]], 
       " bin(s) is/are created!"}]]]

This one works quite nice and gives list as binned in requested amount for suitable lists such as my sample list in the question.

>>> binner[list, 4]
Output: {{1, 2, 2, 3, 4}, {5, 5, 6, 7, 8, 8, 8}, {9, 10, 10, 11, 12, 12, 12, 12, 12, 12, 12}, {13, 14, 15, 16}}

If some of the bins wouldn't have any elements (which means decrease in requested bin amount), function brings cleaned resultant binned list with a string information about the current bin amount. This string info would be useful for long lists binning trials as in my case.

    >>> list2 = {0.1, 0.2, 0.2, 0.3, 0.4, 0.2, 0.4, 0.5, 0.6, 0.4, 0.5, 0.6, 
       0.6, 0.6, 0.7, 0.8, 0.9, 1, 1.1, 1.6, 1.6, 1.7, 1.8, 1.9, 2, 2.3, 2.6};
    >>> binner[list2, 7]
    Output: {{0.1, 0.2, 0.2, 0.3, 0.4, 0.2, 0.4, 0.5, 0.4, 0.5}, {0.6, 0.6, 0.6, 
   0.6, 0.7, 0.8, 0.9, 1}, {1.1}, {1.6, 1.6, 1.7, 1.8, 1.9, 
   2}, {2.3}, {2.6}} -> 6 bin(s) is/are created!

Answered by kosif on February 22, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP