Hej Leute,

heute gibt es Schlangenhappen zum Abendbrot. Ich habe für euch ein kleines Python-Skript geschrieben, um anhand einer Würfelsimulation ein paar Konzepte zu demonstrieren.

Ok, wir fangen langsam an. Eine zufällige Zahl erzeugen geht ganz einfach mit der Library random über die Funktion randint, welche auch alle möglichen weiteren Wahrscheinlichkeitsverteilungen, z.B Normal-, Beta- oder Binomialverteilung.

# ganz einfach den Zufallsgenerator von Python benutzt
import random
for i in range(15):
    print(random.randint(1,6)) 
 
def wuerfeln():
    return(random.randint(1,6))
wuerfeln()

Klassen in Python

Klassen kennt ihr vielleicht aus anderen objektorientierten Programmiersprachen (OOP). Eine Klasse ist im Prinzip der Datentyp eines Objekts und besteht aus Attributen und Methoden. Unsere Klasse heißt Wuerfel und soll – Überraschung – einen Würfel widerspiegeln. Ich erzeuge einen Würfel, indem ich ein neues Objekt der Klasse erzeuge. Das ruft nun den Konstruktor auf. Dabei gebe ich entweder nur die Anzahl Seiten an – die Wahrscheinlichkeit ist dann eine Gleichverteilung, d.h. jede Seite ist gleich wahrscheinlich – oder ich gebe explizit die Wahrscheinlichkeiten der einzelnen Seiten an.

Mit den get- und set-Funktionen können die Attribute, sprich Variablen, der Klasse abgerufen oder gesetzt werden.

Und natürlich soll der Würfel auch etwas machen, nämlich gewürfelt werden. Die Funktion wuerfeln erzeugt eine Zufallsstichprobe der Größe n.

Ist der Würfel fair?

Man spricht von einem fairen Würfel, wenn alle Seiten auf lange Sicht gleich häufig auftreten. Es muss also eine Gleichverteilung vorliegen. Um das statistisch zu testen, benötigen wir zuerst eine Stichprobe, die wir ja schnell mit unserer Funktion wuerfeln erzeugen können. Nun werden die absoluten Häufigkeiten der einzelnen Zahlen mit der Funktion unique aus der library numpy ermittelt. Numpy ist übrigens eine super wichtige Bibliothek, die effeziente Berechnungen ermöglicht und die man als Data Scientist unbedingt gut kennen sollte.

Auf die Häufigkeiten lassen wir nun einen Chi²-Test los. Die Nullhypothese geht von einer Gleichverteilung aus. Ist es sehr unwahrscheinlich, dass die Stichprobe – gegeben die Nullhypthese – gezogen wird, bekommen wir einen kleinen p-Wert. Liegt der p-Wert nun unter einer vorher festgelegten Grenze alpha, z.B. alpha =0,01, wird die Nullhypothese abgelehnt. In unserem Fall heißt das, dass der Würfel also nicht fair ist.

 

Der Python-Code für die Würfelsimulation

Und nun endlich der Code

# so, ab jetzt wird es interessant
import numpy as np
from scipy.stats import chisquare
 
# Definition der Klasse Wuerfel
class Wuerfel(object):        
    #Konstruktor 
    #entweder nur die Anzahl Seiten angeben oder
    #die Anzahl Seiten und die zugehörigen Wahrscheinlichkeiten
    def __init__(self,seiten=6,wahrscheinlichkeiten=None):
        self.seiten = seiten
        if wahrscheinlichkeiten is None:
            self.wahrscheinlichkeiten = np.repeat(1/seiten,seiten)
        else: 
            self.wahrscheinlichkeiten = wahrscheinlichkeiten
 
    def getSeiten(self):
        return self.seiten
    def setSeiten(self,seiten):
        self.seiten=seiten
    def getWahrscheinlichkeiten(self):
        return self.wahrscheinlichkeiten
    def setWahrscheinlichkeiten(self,wahrscheinlichkeiten):
        self.seiten = wahrscheinlichkeiten.size
        self.wahrscheinlichkeiten=wahrscheinlichkeiten
 
    #die Funktion wuerfeln erzeugt ein Array der Länge n    
    def wuerfeln(self,n=1):
        return(np.random.choice(np.arange(1, self.seiten+1), 
                                size=n,p=self.wahrscheinlichkeiten))
 
 
# Wir erzeugen einen regulären 6-seitigen Würfel            
W6 = Wuerfel(seiten=6) 
# nun würfeln wir 100 Mal       
sample1 = W6.wuerfeln(100)
# und zählen, wie häufig jede Zahl vorkommt
haeufigkeiten = np.unique(sample1, return_counts=True)[1]
# Der Chi²-Test prüft auf Gleichverteilung
chisquare(haeufigkeiten)
 
# Jetzt erzeugen wir einen gezinkten 6-seitigen Würfel,
# der viel zu häufig eine 6 würfelt 
W6gezinkt = Wuerfel(seiten=6,wahrscheinlichkeiten=[0.1,0.1,0.1,0.1,0.1,0.5])
# und werfen diesen wieder 100 Mal
sample2 = W6gezinkt.wuerfeln(100)
haeufigkeiten = np.unique(sample2, return_counts=True)[1]
# hier sollte der Chi²-Test die Nullhypothese verwerfen
chisquare(haeufigkeiten)
 
# und noch schnell ein Histogramm gezeichnet
import matplotlib.pyplot as plt
plt.hist(sample1, density=True, bins=6)
plt.hist(sample2, density=True, bins=6)

Happy coding,
Euer Holger