Previously, we sampled values of random variable that is explicitly defined by providing its values and corresponding probabilities. But for well-known distributions like binomial or Poisson, we don't have to calculate these probabilities by ourself because it is already done by developers of libraries that we can use from Python. Let us discuss how can we sample from such random variables as binomial. It can be done in different ways, and the simplest way is to use numpy random module. Let me show how to do it. From numpy.random import binomial. This function generates random variable from binomial distribution, and to make this generation we have to specify n, which is the number of trials or number of coin tossings and p which is the probability of success or probability of getting head, if our random variable is number of heads. For example, we can say that we toss a coin 10 times, and probability of success is order 3. Then every time we invoke this function, we will get the corresponding binomial number. You see, for example, that we have some small numbers in general because of the probability of success. It's smaller than one-half. Let us use our function that we wrote previously to analyze the distribution of the samples that are given by this function. Again as previously, we can add a parameter size and get not a single number and sample from this distribution. We can use the function that we defined previously. Let me recreate this function once again, and now we can save the result of this binomial to some variable like sample, and we can count frequencies of this sample from sample relative. To test how good is our generator, this binomial function, we have to find the actual probabilities of all the values that we have in binomial distribution. This can be done by some explicit calculation using formula so that we discussed in the lecture. But it is also possible to use a function that will calculate these probabilities for us. This function can be found in scipy.stats module, and this is done in the following way. From scipy.stats import binom. In fact, this function defines their corresponding distribution. So let me create this distribution by invoking this function and providing number of trials, number of coin tossings and probability of success, the probability of head just like here, and now I can use this object to get some properties of this kind of random variable. For example, I can get values of probability mass function of this random variable at different points. For example, probability mass function at point 1 is this one. You see that it is quite close to our frequencies that are calculated for our sample. To make this more exact, we can increase sample size and then their corresponding frequencies will be closer to their expected frequency which is given by their corresponding probability. For example, this value of probability mass function at 1 gives us this number, and the obtained frequency is this number. Now let us visualize the frequencies that we get here and corresponding probabilities. To do so, I have to invoke matplotlib again. To draw a graph of this probability mass function, I have to introduce a value x that will define, and they're arranged in which I will draw this graph. To make this range, I need a function from numpy, and let me add one more import , import numpy as np. Then I will use a range from 0-10 with a step 0.1. Then x is just an array of evenly located numbers on segment from 0-10 with this step. So we see there, the result of this operation, and now we can use it to plot their corresponding graph, plt.plot, I have to put values of x here. As the second argument, I have to put their corresponding values of a function, which is pmf. I can put here not only one number but an array of numbers. This function will be will be calculated element-wise. So for each element here, I calculate the corresponding pmf. Let us look at the result. Okay. You see these spikes? This is because here the value of the function is 0 because our random variable x capital cannot take this non-integer values, and we have this spikes at integral numbers. So it is probably better to use different visualization here. Now every point on this graph just corresponds to a pair of x and y here. So we can draw two graphs. First graph which is given by this probability mass function and another graph which is given by our sample, the bar plot like we plotted previously. To do so, we have to make plt.bar, and let me save this count frequencies somewhere. Now I can just plot freqs.keys, freqs.values. I have to convert most of them to lists, otherwise, plt.bar will not work. Let me use different color, for example, here. Here you see that the probabilities that we have from theorem are a very good approximation to the relative frequencies that we obtained by our generation. Also we can investigate how changing of the values of n and p will affect this graph. Let me copy these two lines, and let me copy some other lines. So again we need this random variable, and we need this sample. To avoid it changing one value in different places, let me introduce variables, n small which is number of trials and p which is probability of success, and put it here, and here. So now the result is the same but we can change for example probability of success and get different pictures. You see, for example, that when you increase probability of success, you will get much more cases of n, their corresponding value is closer to 10. We can also change this n, number of trials. For example we can put 5 here, and you see that it affects their graph. The maximum possible value of our random variable is 5. We can also change this sample size. For example, if we decrease it to 10 then you see that the obtained frequencies can be different from their probabilities. But as we increase this sample size, the correspondence between frequencies and probabilities becomes stronger. If the sample size is 10,000, we almost have no difference between these red points and the top level of these rectangles. If we increase the sample size further, we have even better correspondence. So in this way we can analyze any random variable that is generated by numpy. Actually there are a lot of predefined random variables. For us it can be interesting to study Poisson or geometric distributions.