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$
  • $\begingroup$ Look at BinLists $\endgroup$ – Bob Hanlon Sep 22 '16 at 23:43
  • 1
    $\begingroup$ "Nth Mth of a list" is unclear. Please give a concrete example. $\endgroup$ – David G. Stork Sep 23 '16 at 0:23
  • $\begingroup$ I gave concrete examples in the question. The 3rd 8th segment of a list, for example. @DavidG.Stork $\endgroup$ – Mason Guffey Sep 23 '16 at 0:28
  • 1
    $\begingroup$ um, what? repeat the request for an example. $\endgroup$ – george2079 Sep 23 '16 at 3:36
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)}
| improve this answer | |
$\endgroup$
  • 1
    $\begingroup$ Try mylist = Range[33];. Then mynm[mylist, 4, 4] is missing a item of the list. Namely 33. $\endgroup$ – Edmund Sep 23 '16 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.

| improve this answer | |
$\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}

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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