Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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, #[[18]] &];

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][[1]]
s = Table[RandomSample[g[[i]], l[[i]]], {i, 1, Length[g]}]
p = Sort[Position[data, #][[1]][[1]] & /@ #] & /@ 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][[1]]]

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

edit:

If n = 7

enter image description here

If n = 21

enter image description here

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, #[[18]] &])], n - 7];
  h~Union~k]
share|improve this question
1  
Sorry, I'm having trouble understanding this. Could you try again to explain, please? –  Mr.Wizard 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). –  Margus 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?" –  belisarius 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.] –  Daniel Lichtblau Jan 2 '13 at 16:36
add comment

1 Answer

up vote 1 down vote accepted

This first chooses one element from each subset, and then takes the rest from the complement using the whole set (discarding those previously taken). It doesn't assume a fixed number of classes, and calculates it from the length of the first choice.

f[data_List, n_Integer] := 
   #~Union~RandomSample[DeleteCases[data, Alternatives @@ #], n - Length@#] &@
                                              (RandomChoice /@ GatherBy[data, #[[18]] &])
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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