Package: sample_space
…is a very lightweight Python API for simulating sample spaces,
events, random variables, and (conditional) distributions.ExampleCheck out theiPython notebookor read the
following:fromsample_spaceimport*classNCoinTosses(Experiment):def__init__(self,n,p):self.n=nself.p=pdefrerun(self):self.tosses=[Bern(self.p)for_inrange(self.n)]defheads(self):returnsum(self.tosses)defthere_are_at_least_two_heads(self):returnself.heads()>=2deffirst_toss_heads(self):returnself.tosses[0]space=SampleSpace(NCoinTosses(10,0.5),iters=20000)# ask for probability of any truthy methodprint('        P(#H>=2):',space.probability_that('there_are_at_least_two_heads'))# alias for the above, if it's more grammaticalprint('           P(H1):',space.probability_of('first_toss_heads'))# change the number of iterationsprint(' P(H1), 1K iters:',space.probability_of('first_toss_heads',iters=1000))# ask for probabilities of functions of random variablesprint('         P(#H>5):',space.probability_that(['heads',is_greater_than(5)]))# ask for conditional probabilitiesprint('      P(#H>5|H1):',space.probability_that(['heads',is_greater_than(5)],given=['first_toss_heads']))print('      P(H1|#H>5):',space.probability_of('first_toss_heads',given=[['heads',is_greater_than(5)]]))print(' P(#H>5|H1,H>=2):',space.probability_that(['heads',is_greater_than(5)],given=['first_toss_heads','there_are_at_least_two_heads']))# ask for expectations, variances, and moments, conditionally or absolutelyprint('           E(#H):',space.expected_value_of('heads'))print('        E(#H|H1):',space.expected_value_of('heads',given=['first_toss_heads']))print('         Var(#H):',space.variance_of('heads'))print('      Var(#H|H1):',space.variance_of('heads',given=['first_toss_heads']))print('1st moment of #H:',space.nth_moment_of('heads',1))print('2nd moment of #H:',space.nth_moment_of('heads',2))print('3rd moment of #H:',space.nth_moment_of('heads',3))print('4th moment of #H:',space.nth_moment_of('heads',4))print('  Skewness of #H:',space.nth_moment_of('heads',3,central=True,normalized=True),'(using nth_moment_of w/ central=True, normalized=True)')print('  Skewness of #H:',space.skewness_of('heads'),'(using skewness_of)')print('  Kurtosis of #H:',space.kurtosis_of('heads'))# some plotsfig=plt.figure(figsize=(14,3))# plot distribution histogramsfig.add_subplot(121)space.plot_distribution_of('heads')# pass kwargsplt.legend()# plot conditional distribution histogramsfig.add_subplot(122)space.plot_distribution_of('heads',given=['first_toss_heads'],bins=10)# can pass kwargsplt.legend()plt.show()Which should output (plus some plots):P(#H>=2): 0.98975
           P(H1): 0.502
 P(H1), 1K iters: 0.48
         P(#H>5): 0.37665
      P(#H>5|H1): 0.5076294006183305
      P(H1|#H>5): 0.6580109757729888
 P(#H>5|H1,H>=2): 0.49361831442463533
           E(#H): 4.9983
        E(#H|H1): 5.48924623116
         Var(#H): 2.4486457975
      Var(#H|H1): 2.31806506582
1st moment of #H: 4.99245
2nd moment of #H: 27.5097
3rd moment of #H: 163.13055
4th moment of #H: 1015.54155
  Skewness of #H: -0.00454435802967 (using nth_moment_of w/ central=True, normalized=True)
  Skewness of #H: 0.00414054522343 (using skewness_of)
  Kurtosis of #H: 2.78225928171Why?Mostly to avoid bugs / reduce boilerplate in statistical simulations for
sanity-checking homework solutions. But also to get a better
understanding of probability theory.Sample spacesare a
core concept in probability theory. They encapsulate the idea of
repeatedly running an experiment with random results. Almost every
important statistical quantity – the probability of an event, or any
moment of a random variable – is always defined relative to a sample
space. So if you’re trying to program meaningful simulations (and if
you’re more concerned with expressiveness than performance), you might
as well organize your code by explicitly defining one.Installation / UsageFirst runpip install sample_spaceandimportthe library. Then define a subclass ofExperimentthat responds torerun(self).rerunshould perform a random
experiment and store one or more basic results as instance variables. If
you want to define more complex events or random variables, you can
express them as instance methods.Then, initialize aSampleSpacewith an instance of yourExperiment. You can query your sample space for theprobability_that/probability_ofan event, or you can query it
for thedistribution_of,expected_value_of,variance_of,skewness_of,kurtosis_of, ornth_moment_ofof random
variable (which can also just be an event, in which case it will be
interpreted as an indicator). Finally, for any of these methods, you can
pass agivenkeyword argument with a list of events, which will make
any results you obtain conditional on all of those events occurring.
Behind the scenes,SampleSpacewill justrerunyour experiment
10000 times and average your random variable or count how often an event
occurs (conditionally). You can pass aniterskeyword argument to
any method or toSampleSpace.__init__to increase the number of
iterations.To reference events or random variable, pass the string name of an
instance variable or instance method of your experiment, or pass an
array with a variable/method name and a lambda function. For example:space=SampleSpace(CoinTossExperiment(10))space.probability_that('first_toss_is_heads')space.probability_that(['n_heads',lambdah:h>5])space.expected_value_of('n_heads')space.expected_value_of('n_heads',given=['first_toss_is_heads'])space.probability_that('first_toss_is_heads, given=[['n_heads', lambda h: h > 3], 'last_toss_is_heads'])Additionally,sample_spacedefines a few helpful lambda-returning
methods (is_greater_than(x),is_less_than(x),is_at_least(x),is_at_most(x),equals(x)) for convenience.
Of course, you could also define instance methods on yourExperimentto accomplish the same goal.The library also exposes a few basic sampling functions (Bern(p),Bin(n,p),RandomSign(p), andCateg(categories, weights)) to
assist with defining experiments.Lite VersionIf you’d prefer not to define a fullExperimentclass, you can also
just define a random event / random variable function that returns
either a boolean or a number, and callprobability_that/expected_value_of:importsample_spaceasssdefweighted_coin_flip_is_heads(p=0.4):returnss.Bern(p)defn_weighted_heads(n=100,p=0.4):returnsum(weighted_coin_flip_is_heads(p)for_inrange(n))print(ss.probability_that(weighted_coin_flip_is_heads))print(ss.probability_that(lambda:weighted_coin_flip_is_heads(0.5))print(ss.expected_value_of(n_weighted_heads))print(ss.expected_value_of(lambda:n_weighted_heads(200,0.3)))LicenseMIT