2
$\begingroup$

With all the tools and commands for segmenting lists, I'm having a hard time finding something to do the following: I want to programmatically subset the Nth Mth of a list. This could be the 1st 4th, the 3rd 16th, or so on. The function can return either the subsetted data set, or (preferably) just the indices to the data.

The idea here is so, for instance, I can generate a histogram that windows the entire data set in 1/3, 1/4, 1/5, 1/n etc blocks, with a window size that can easily be adjusted. What I don't want to have to do is use a whole bunch of Length[]'s in the part specification.

$\endgroup$
4
  • $\begingroup$ Look at BinLists $\endgroup$
    – Bob Hanlon
    Commented Sep 22, 2016 at 23:43
  • 1
    $\begingroup$ "Nth Mth of a list" is unclear. Please give a concrete example. $\endgroup$ Commented Sep 23, 2016 at 0:23
  • $\begingroup$ I gave concrete examples in the question. The 3rd 8th segment of a list, for example. @DavidG.Stork $\endgroup$ Commented Sep 23, 2016 at 0:28
  • 1
    $\begingroup$ um, what? repeat the request for an example. $\endgroup$
    – george2079
    Commented Sep 23, 2016 at 3:36

3 Answers 3

4
$\begingroup$

First you partition the list into the $m$ portions (rounded, in case these are not of equal size), then take the $n$th of these:

mynm[list_List, n_Integer, m_Integer] := 
  Partition[list, Round[Length[list]/m]][[n]];

For instance:

mylist = Table[RandomReal[],100];

mynm[mylist, 3, 8]

gives the third eighth of that list.

If you just want the indexes to the first and last element in your subset:

{Length[list]Round[n/m],Length[list](Round[(n+1)/m]-1)}
$\endgroup$
1
  • 1
    $\begingroup$ Try mylist = Range[33];. Then mynm[mylist, 4, 4] is missing a item of the list. Namely 33. $\endgroup$
    – Edmund
    Commented Sep 23, 2016 at 1:55
1
$\begingroup$

A direct calculation of indices solution.

ClearAll[subPart];
subPart[list_, nthPart_Integer?Positive, proportion_ /; Between[proportion, {0, 1}]] /; 
  proportion (nthPart - 1) <= 1 :=
 With[{len = Length[list]},
  list[[Floor[len proportion (nthPart - 1)] + 1 ;; 
    Min[Floor[len proportion nthPart], len]]]
  ]

Then

dat = Range[33];
subPart[dat, #, 1/4] & /@ Range[4]
{{1, 2, 3, 4, 5, 6, 7, 8}, {9, 10, 11, 12, 13, 14, 15, 16}, 
 {17, 18, 19, 20, 21, 22, 23, 24}, {25, 26, 27, 28, 29, 30, 31, 32, 33}}
dat = Range[11];
subPart[dat, #, 1/4] & /@ Range[4]
{{1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}}
dat = Range[10];
subPart[dat, #, .2] & /@ Range[5]
{{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}}

The length of the sub-list will vary as with percentile of the cuts over the length of the list.

Hope this helps.

$\endgroup$
1
$\begingroup$

This partitions into m parts (size uniform as much as possible in case when the dataset is not divisible into equal-size subsets) and returns the nth one:

partitionNM[data_List, n_Integer, m_Integer] := 
 Module[{round, interv, part},
  SetAttributes[round, {Listable}];
  round[x_] := If[FractionalPart[x] < 0.5, Floor[x], Ceiling[x]];
  interv[x_] := Prepend[Table[i/x Length@data, {i, 1, x}], 1];
  part = Partition[round@interv[m], 2, 1];
  Take[data, part[[n]]]
  ]


partitionNM[Range[33], 4, 4]

{25, 26, 27, 28, 29, 30, 31, 32, 33}

$\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.