# Random sample with gap sizes

Lets say I have 101 instances of data with multiple attributes. In particular case, one attribute has 7 unique values. I want to get 7<=n<=101 element positions from data, in a way that it contains at least 1 of each unique attribute case.

First I get the example data and gather it by particular attribute:

data = Import["https://raw.github.com/BioGeek/aima/master/aima-data-read-only/zoo.csv"];
g = GatherBy[data, #[] &];


List g of lists with element sizes h

h = Length[#] & /@ g (*{41,13,20,10,8,4,5}*)


Following works in the best case scenario

n = RandomInteger[{Length[g], Length[data]}]
l = RandomSample[RandomSample[#] & /@ IntegerPartitions[n, {Length[g]}], 1][]
s = Table[RandomSample[g[[i]], l[[i]]], {i, 1, Length[g]}]
p = Sort[Position[data, #][][] & /@ #] & /@ s


Example result:

{{30,33},{8,62},{57,72,96,101},{14,73,78,82,86},{25,40,43,89},{26,27,53,90},{77,81,91,92}}


I can bruteforce, but I do not like the idea.

While[MemberQ[Table[h[[i]] >= l[[i]], {i, 1, Length[h]}], False],
l = RandomSample[RandomSample[#] & /@ IntegerPartitions[n, {Length[g]}], 1][]]


How do I find random sample l so it is less then gap sizes h?

edit:

If n = 7 If n = 21 Problem is that h = {41,13,20,10,8,4,5} and even if n = 11 then l = {1,1,1,1,1,5,1} that is invalid as there are not enough elements in that sublist.

edit 2

f[data_List, n_Integer] := Module[{data1 = data, h, k},
k = RandomSample[DeleteCases[data1, Alternatives @@
(h = RandomChoice /@ GatherBy[data1, #[] &])], n - 7];
h~Union~k]

• Sorry, I'm having trouble understanding this. Could you try again to explain, please? Jan 2 '13 at 15:21
• If 'n = 7', i want to take sample positions of 7 unique elements from the data. If n is larger, i want to take more elements. Selection must have 1 element of each attribute 18 category {mammal, fish, bird, ...}(7 in total). Jan 2 '13 at 15:59
• I can't understand your sentence "How do I find random sample l so it is less then gap sizes h?" Jan 2 '13 at 16:20
• Why not base the number of elements chosen in a given sublist on the length of that sublist? That way you will never request more than you have. [Note: You really have not stated clearly what is your "randomness" requirement. Thus it is difficult to give a specific answer.] Jan 2 '13 at 16:36

f[data_List, n_Integer] :=