Ab Python v3.6
konnte random.choices
verwendet werden, um eine Liste
von Elementen der angegebenen Größe aus der gegebenen Population mit optionalen Gewichten zurückzugeben.
random.choices(population, weights=None, *, cum_weights=None, k=1)
-
population : Liste
mit eindeutigen Beobachtungen. (Wenn leer, wirft es IndexError
)
-
weights : Genauere relative Gewichte, die für die Auswahl erforderlich sind.
-
cum_weights : Kumulative Gewichte, die für die Auswahl erforderlich sind.
-
k : Größe(len
) der auszugebenden Liste
. (Standard len()=1
)
Einige Einschränkungen:
1) Es wird eine gewichtete Stichprobe mit Wiederholung verwendet, sodass die gezogenen Elemente später ersetzt werden. Die Werte in der Gewichtssequenz selbst sind nicht wichtig, aber ihr relatives Verhältnis.
Im Gegensatz zu np.random.choice
, das nur Wahrscheinlichkeiten als Gewichtungen annehmen kann und auch sicherstellen muss, dass die Summierungen der einzelnen Wahrscheinlichkeiten bis zu 1 erfolgen, gibt es hier keine solchen Bestimmungen. Solange sie zu numerischen Typen gehören (int/float/fraction
außer vom Typ Decimal
), funktionieren sie dennoch.
>>> import random
# Gewichte als ganze Zahlen
>>> random.choices(["weiß", "grün", "rot"], [12, 12, 4], k=10)
['grün', 'rot', 'grün', 'weiß', 'weiß', 'weiß', 'grün', 'weiß', 'rot', 'weiß']
# Gewichte als Gleitkommazahlen
>>> random.choices(["weiß", "grün", "rot"], [.12, .12, .04], k=10)
['weiß', 'weiß', 'grün', 'grün', 'rot', 'rot', 'weiß', 'grün', 'weiß', 'grün']
# Gewichte als Brüche
>>> random.choices(["weiß", "grün", "rot"], [12/100, 12/100, 4/100], k=10)
['grün', 'grün', 'weiß', 'rot', 'grün', 'rot', 'weiß', 'grün', 'grün', 'grün']
2) Wenn weder weights noch cum_weights angegeben sind, werden die Auswahlen mit gleicher Wahrscheinlichkeit getroffen. Wenn eine Gewichtungssequenz bereitgestellt wird, muss sie die gleiche Länge wie die Populationssequenz haben.
Das Angeben sowohl von weights als auch von cum_weights führt zu einem TypeError
.
>>> random.choices(["weiß", "grün", "rot"], k=10)
['weiß', 'weiß', 'grün', 'rot', 'rot', 'rot', 'weiß', 'weiß', 'weiß', 'grün']
3) cum_weights sind typischerweise das Ergebnis der itertools.accumulate
-Funktion, die in solchen Situationen wirklich nützlich sind.
Aus der verlinkten Dokumentation:
Intern werden die relativen Gewichte in kumulative Gewichte umgewandelt, bevor Auswahl getroffen wird, daher spart das Bereitstellen der kumulativen Gewichte Arbeit.
Also produzieren entweder die Bereitstellung von Gewichte=[12, 12, 4]
oder cum_weights=[12, 24, 28]
für unseren konstruierten Fall das gleiche Ergebnis und Letzteres scheint schneller / effizienter zu sein.