Pourquoi la fonction rdd.sample()
on Spark RDD renvoie un nombre différent d'éléments même si le paramètre fraction est le même? Par exemple, si mon code est comme ci-dessous:
val a = sc.parallelize(1 to 10000, 3)
a.sample(false, 0.1).count
Chaque fois que j'exécute la deuxième ligne du code, il renvoie un nombre différent différent de 1000. En fait, je m'attends à voir 1000 à chaque fois, bien que les 1000 éléments puissent être différents. Quelqu'un peut-il me dire comment obtenir un échantillon dont la taille est exactement égale à 1000? Merci beaucoup.
Si vous voulez un échantillon exact, essayez de faire
a.takeSample(false, 1000)
Mais notez que cela renvoie un tableau et non un RDD
.
Quant à savoir pourquoi la a.sample(false, 0.1)
ne renvoie pas la même taille d'échantillon: c'est parce que spark utilise en interne quelque chose appelé échantillonnage de Bernoulli pour prendre l'échantillon. L'argument fraction
ne représente pas la fraction de la taille réelle du RDD. Il représente la probabilité que chaque élément de la population soit sélectionné pour l'échantillon, et comme le dit wikipedia:
Étant donné que chaque élément de la population est considéré séparément pour l'échantillon, la taille de l'échantillon n'est pas fixe mais suit plutôt une distribution binomiale.
Et cela signifie essentiellement que le nombre ne reste pas fixe.
Si vous définissez le premier argument sur true
, il utilisera quelque chose appelé échantillonnage de Poisson , ce qui entraîne également une taille d'échantillon résultante non déterministe.
Mise à jour
Si vous voulez vous en tenir à la méthode sample
, vous pouvez probablement spécifier une probabilité plus grande pour le paramètre fraction
puis appeler take
comme dans:
a.sample(false, 0.2).take(1000)
Cela devrait, la plupart du temps, mais pas nécessairement toujours, donner un échantillon de 1 000 personnes. Cela pourrait fonctionner si vous avez une population suffisamment importante.
Une autre façon peut être de prendre d'abord Sample puis de faire RDD. Cela peut être lent avec de grands ensembles de données.
sc.makeRDD(a.takeSample(false, 1000, 1234))