<jupyter_start><jupyter_text>Problem Statement The following assignment concerns the numpy.random package in Python. You are required to create a Jupyter notebook explaining the use of the package, including detailed eplanations of at least five of the distributions provided for in the package. There are 4 distinct tasks to be carried out in your Jupyter noteboook.  References- https://docs.scipy.org/doc/numpy-1.15.1/reference/routines.random.html- https://realpython.com/python-random/- https://www.tutorialspoint.com/How-to-use-Python-Numpy-to-generate-Random-Numbers- https://www.mathworks.com/help/matlab/ref/rand.html- http://mathworld.wolfram.com/NormalDistribution.html- https://plot.ly/numpy/randint/- https://analytics4all.org/tag/python-numpy-random-integers- https://towardsdatascience.com/first-step-in-data-science-with-python-numpy-5e99d6821953- http://nbviewer.jupyter.org/github/mbakker7/exploratory_computing_with_python/blob/master/notebook4_functions/py_exploratory_comp_4_sol.ipynb- http://people.duke.edu/~ccc14/pcfb/numpympl/MatplotlibBasics.html- http://www.imagexd.org/tutorial/lessons/1_ransac.htm- https://www.digitalocean.com/community/tutorials/how-to-define-functions-in-python-3- https://www.slideshare.net/RizwanSa/probability-distributions-sampling-distributions-and-central-limit-theorem- https://machinelearningmastery.com/introduction-to-random-number-generators-for-machine-learning/- https://plot.ly/matplotlib/exponential-fits/- https://www.mathsisfun.com/algebra/trig-sin-cos-tan-graphs.html- https://en.wikipedia.org/wiki/Cryptography- https://www.quora.com/Why-are-random-numbers-important- https://en.wikipedia.org/wiki/Randomness- https://www.techopedia.com/definition/31706/random-number- https://en.wikipedia.org/wiki/Random_number_generation- https://bigdata-madesimple.com/how-to-implement-these-5-powerful-probability-distributions-in-python/- https://en.wikipedia.org/wiki/Normal_distribution- https://en.wikipedia.org/wiki/Mersenne_Twister- https://stackoverflow.com/questions/22994423/difference-between-np-random-seed-and-np-random-randomstate- https://explorable.com/chi-square-test https://www.packtpub.com/mapt/book/application_development/9781783555253/2/ch02lvl1sec16/probability-distributions- http://blog.cloudera.com/blog/2015/12/common-probability-distributions-the-data-scientists-crib-sheet/- https://explorable.com/chi-square-test- https://en.wikipedia.org/wiki/Chi-squared_distribution- https://www.packtpub.com/mapt/book/big_data_and_business_intelligence/9781785282287/3/ch03lvl1sec42/fitting-aggregated-counts-to-the-poisson-distribution- https://stattrek.com/probability-distributions/binomial.aspx- https://en.wikipedia.org/wiki/Exponential_distribution- https://math.stackexchange.com/questions/1050184/difference-between-poisson-and-binomial-distributions  1. Explain the overall purpose of the package **The numpy package**Numpy, short for Numerical Python, provides provides a collection of high level mathematical functions to operate on arrays to assist in manipulating numerical data. A function is a block of code/instructions that performs an action/calculation and, once defined, can be repeated. [Ref: define a function](https://www.digitalocean.com/community/tutorials/how-to-define-functions-in-python-3) In order to use these mathematical numpy functions, we need to import the numpy package using the syntax ```import numpy```. Any function from the numpy package can then be called as ```numpy.function()```. Numpy package lines of code can be shortened if we import numpy using the syntax ```import numpy as np```. Any function from the numpy package can then be called using the line of code ```np.function()```. [Ref: Numpy package](http://nbviewer.jupyter.org/github/mbakker7/exploratory_computing_with_python/blob/master/notebook4_functions/py_exploratory_comp_4_sol.ipynb) **The matplotlib package**The matplotlib package and pyplot subpackage are graphics and plotting liraries in python are regularly used to produce plots and other two-dimensional data visualizations of numpy functions. The matplotlib package and pyplot subpackage are heavily dependent on the numerical functions within the numpy package.  In order to produce these  plotting functions, we need to import the matplotlib package and pyplot subpackage using the syntax ```import matplotlib.pyplot```. Any function from the matplotlib package and pyplot subpackage can then be called as ```matplotlib.pyplot.function()```. Matplotlib package and pyplot subpackage lines of code can be shortened if we import matplotlib and pyplot using the syntax ```import matplotlib.pyplot as plt```. Any function from the matplotlib package and pyplot subpackage can then be called using the line of code ```plt.function()```. [Ref: Matplotlib package](http://people.duke.edu/~ccc14/pcfb/numpympl/MatplotlibBasics.html) See below a representation of the matemathical sine and cosine functions. In this plot, I am importing the matplotlib (& pyplot) package required to produce my plot. I am importing numpy to activate the mathematical functions contained within this package. I am using the np.arange function to set my variable as x. The numpy arange funtion is very similar to the range function in python. However, instead of generating integers in a specfic sequence, the numpy arange function generates floating point numbers (or decimals) in a specific sequence. I am using the np.pi function to define the sequence in this argument.By calling the np.arange function with the below arguments, we are asking numpy return all the values between -2 x pi(including -2 x pi) and 2 (not including 2 x pi). I am also asking numpy to provide me with these values in increments of 0.01.I am then calling the plot function with an argument of x and the sin and cos of x respectively to make 2 x plots on the x axis. The below plot describes the relationship between Sin and Cos. They follow each other exactly π/2 radians (90°) apart. [Ref:Sin Cos](https://www.mathsisfun.com/algebra/trig-sin-cos-tan-graphs.html)<jupyter_code># Use numatplotlib & pyplot libraries to plot a 2d plot
import matplotlib.pyplot as plt

# Use functions in numpy library to analyse file
import numpy as np

# Sets the varaiable as x
x = np.arange(-2.0 * np.pi, 2.0 * np.pi, 0.1)

# Plots the sin function on the x axis
plt.plot(x, np.sin(x), 'g.', label="sin")
# Plots the cos function on the x axis
plt.plot(x, np.cos(x), 'b.', label="cos")
plt.title("Sin Cos")

plt.legend()
plt.show()<jupyter_output><empty_output><jupyter_text>**The random package** The random package is another package contained within the numpy library which is used to generate pseudorandom numbers. Computers can't generate random numbers, they can only generate numbers pseudorandom numbers which are they are generated by an algorithim. The behaviour of an algorithm is quite deterministic and is based on the seed on the random number generator. The random package calculates random numbers one value at a time.Random numbers are used in the practice of cryptography and encryption. Cryptography produces protocols for information security such chip-based payment cards, computer passwords etc. [Ref:Cryptograpy](https://en.wikipedia.org/wiki/Cryptography)See below a snippet of code which calculates a floating point uniform random number netween 1 and 10.<jupyter_code># Use the random package to calculate random numbers
import random

# Sets value as the variable
value = random.uniform(1, 10)
print("Prints a random floating point value between 1 and 10:", value)<jupyter_output>Prints a random floating point value between 1 and 10: 9.713995644902196<jupyter_text>**The numpy.random subpackage**The random is a subpackage contained within the numpy package (and not within the random package). This subpackage is similar to the random package but instead of generating one random value at a time, it generates whole arrays of sample values from many kinds of probability distributions. After the numpy package has been imported as ```import numpy as np```, functions from the random module can be called as ```np.random.function()```. [Ref: Random subpackage](http://nbviewer.jupyter.org/github/mbakker7/exploratory_computing_with_python/blob/master/notebook4_functions/py_exploratory_comp_4_sol.ipynb)See below an intersting 4d scatter plot which is plotting 4 variables. x and y are arrays of random values with a uniform distribution while z is an array random values with a normal distribution. c is an array of random integers.<jupyter_code># Import matplotlib
import matplotlib.pyplot as plt
# Import numpy
import numpy as np

# Set the values of x using a numpy random function with a uniform distribution
x = np.random.uniform(0.0, 10.0, 100)
# Set the values of y using a numpy random function with a uniform distribution
y = np.random.uniform(0.0, 100.0, 100)
# Set the values of z using a numpy random function with a normal distribution
z = np.random.normal(100.0, 40.0, 100)
# Set the values of c using a numpy random integers function
c = np.random.randint(0, 20, 100)

# Plot the 4 variables on a scatter plot
plt.scatter(x, y, c=c,s=z)
plt.show()<jupyter_output><empty_output><jupyter_text>2. Explain the use of the "Simple random data" and "Permuations" functions. **What is a random number?**A random number is a number generated by a process or an unpredictible event. This process or event has a lack of pattern. The outcome of this event cannot be subsequently reliably reproduced. Therefore we can say that randomness is a measure of uncertainty of an outcome. Other times, we repeat the unpredictable event many times over, to gain an understanding of what usually happens and detect trends. Theses types of techniques are useful in the areas of meteorology or in scientific experimentation.[Ref: Randomness](https://en.wikipedia.org/wiki/Randomness)Classic examples of random number generation include the rolling of dice, coin flipping and  the shuffling of playing cards. However, these techniques are very mechanical. The generation of sufficiently random numbers using these processes would also require a lot of time/work. Sufficiently random numbers are important statistical analysis and probability theory. Many things in real life are so complicated that they appear random. To simulate those processes we need random numbers.[Ref: Random numbers](https://en.wikipedia.org/wiki/Randomness)In modern times, random numbers are produced with the help of a random number generator which includes a large set of numbers and a mathematical algorithm. This mathematical algorithm gives equal probability to all numbers occurring in the specified distribution. However, computers can't generate random numbers , they can only generate numbers pseudorandom numbers which are they are generated by an algorithim. These numbers look random but are actually deterministic. A Pseudo Random Number Generator starts from a state known as the seed state. The PRNG can can be reproduce these random numbers later if the seed state is known. [Ref: Random number generation](https://en.wikipedia.org/wiki/Random_number_generation) **The "Simple random data" and "Permutations" functions**In this section, I'll desribe the "Simple random data" and "Permuations" segments of the random sampling (numpy.random) documentation.[Ref: Numpy documentation](https://docs.scipy.org/doc/numpy-1.15.1/reference/routines.random.html)There are 4 different sections in random sampling (numpy.random) documentation. The "Simple random data" and "Permutations" sections of the documentation contain numpy functions for the generatation of random data for everyday purposes. Some assumptions about the types of random numbers generated have been made in these functions. The "Simple random data" functions are based on the functions contained in the "Distributions" section. The functions in the "Distributions" section are all based on probability distributions. The final section of the documention "Random Generator" contains functions for the generation of pseudo random numbers. Below, I have investigated some of the numpy.random functions from the random sampling documentaion. See below a review of some of the functions in the "Simple random data" and "Permutations" sections. **.rand**The rand function generates random numbers in the interval [0,1) that are distributed uniformly (all numbers are equally possible). In mathematics, this is notation for an interval - section of the real line between 0 and 1. The square bracket means 0 is included and round bracket means 1 is not included. Rand function can give you a number between 0 (including 0) and 1 (not including 1).The rand function generates a random floating point number on the fly, see below.<jupyter_code>np.random.rand()<jupyter_output><empty_output><jupyter_text>The argument of the rand function determines the shape of the array. See below a rand function has created an array which contains 3 other arrays. Each of these contain 2 elements and the elements look like floating numbers.<jupyter_code>np.random.rand(3, 2)<jupyter_output><empty_output><jupyter_text>**.randn** The randn function generates random numbers in the interval [0,1) from a normal distribution.The randn function generates a random floating point number on the fly, see below.<jupyter_code>np.random.randn()<jupyter_output><empty_output><jupyter_text>The argument of the randn function determines the shape of the array. See below a randn function has created an array which contains 3 other arrays. Each of these contain 2 elements and the elements look like floating numbers.<jupyter_code>np.random.randn(3, 2)<jupyter_output><empty_output><jupyter_text>**.randint** The randint function generates random integers from the “discrete uniform” distribution.The argument if the randint function contains from which random numbers can be selected.<jupyter_code>np.random.randint(1,10)<jupyter_output><empty_output><jupyter_text>**.choice**The choice function randomly shuffles the elements of the original array in the argument of the function into another array. The elements of the original array can be repeated in the new array.<jupyter_code>np.random.choice([1,2,3,4,5],size=5)<jupyter_output><empty_output><jupyter_text>**.shuffle(sequence)**The shuffles function randomly shuffles the elements of the original array in the argument of the function into another array. The elements of the original array are not repeated in the new array.<jupyter_code>import numpy as np

# Sets x as the variable (sequence) for the range 0 but not including 10
x = np.arange(10)
# Let's look at x
x
# Shuffles the input sequence x
np.random.shuffle(x)
# Let's look at x
x<jupyter_output><empty_output><jupyter_text>3. Explain the use and purpose of at least five "Distributions" functions.**Probability Distributions**A probability distribution is a mathematical function that links all the outcomes of a statistical experiment with the probability of occurrance of different possible outcomes. The distribution of a statistical data set is a listing or function showing all the possible values (or intervals) of the data and how often they occur. A distribution allows a potentially large amount of data to be summarized very efficiently.  [Ref: Probability Distributions](https://www.packtpub.com/mapt/book/application_development/9781783555253/2/ch02lvl1sec16/probability-distributions)See below a table of the most common various probabilty distributions.[Ref: Table of probability distributions](http://blog.cloudera.com/blog/2015/12/common-probability-distributions-the-data-scientists-crib-sheet/) In this section, I will examine some of these probility distributions as well as their relationships with other probaility distributions. ![image.png](attachment:image.png) **Normal and Chi-Squared Distributions**<jupyter_code># Import Matplotlib
import matplotlib.pyplot as plt

#Import numpy
import numpy as np

# Plot the first of 2 plots using the random normal function
plt.subplot(1, 2, 1)
x = np.random.normal(0.0, 1.0, 10000)
plt.title("Normal Distribution")
plt.hist(x)

# Plot the second of 2 plots using the random chisquare function
plt.subplot(1, 2, 2)
samples = np.random.chisquare(1,100)
plt.hist(samples, bins=10)
plt.title("Chi-Squared Distribution")

# Output the results
plt.show()<jupyter_output><empty_output><jupyter_text>**What is a normal distribution?**The standard normal distribution or the Gaussian distribution is the most widely known and used of all probability distributions.  Many distributions occur frequently in data analysis, but none so much as the normal distribution. It is instantly recognisable by it's bell shaped curve or symmetrical distribution. Median and mode are the same and the data is symmetrical.  [Ref: Normal distribution](https://en.wikipedia.org/wiki/Normal_distribution)In the above function, I have asked the numpy to return an array 10,000 random values and to return them in a normal probability distribution. I have called ```np.random.normal``` function with an argument which centres the values around 0, has a standard deviation of 1.0 and returns an array of 10,000 random vaues. The histograms tell you approximately how data is distributed throughout its range.**What is a chi-squared distribution?**The chi-squared dustribution is related to the standard normal distribution. A chi-squared distribution constructed by squaring a single standard normal distribution is said to have 1 degree of freedom. [Ref: Chi-squared distribution](https://en.wikipedia.org/wiki/Chi-squared_distribution)In the above function, I have asked the numpy to return an array 100 random values and to return them in a chi-squared probability distribution. I have called ```np.random.chisquare``` function with an argument which centres the values around 1 and returns an array of 100 random vaues. The histograms tell you approximately how data is distributed throughout its range.The Chi-square test can be used to test whether the observed data differs significantly from the expected data. [Ref: Chi-square distribution](https://explorable.com/chi-square-test)The simplest chi-squared distribution is the square of a standard normal distribution. So wherever a normal distribution could be used for a hypothesis test, a chi-squared distribution could be used.  [Ref: Chi-squared v normal](https://en.wikipedia.org/wiki/Chi-squared_distribution) **Normal and Poisson Distributions**<jupyter_code># Import matplotlib
import matplotlib.pyplot as plt

# Import numpy
import numpy as np

# Plot the first of 2 plots using the random normal function
plt.subplot(1, 2, 1)
x = np.random.normal(0.0, 1.0, 10000)
plt.title("Normal Distribution")
plt.hist(x)

# Plot the second of 2 plots using the random poisson function
plt.subplot(1, 2, 2)
# Adapted from: https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.poisson.html#numpy.random.poisson
samples = np.random.poisson(5, 10000)
count, bins, ignored = plt.hist(samples, 14, density=True)
plt.title("Poisson Distribution")

# Output the results
plt.show()<jupyter_output><empty_output><jupyter_text>**What is a normal distribution?**The standard normal distribution or the Gaussian distribution is the most widely known and used of all probability distributions.  Many distributions occur frequently in data analysis, but none so much as the normal distribution. It is instantly recognisable by it's bell shaped curve or symmetrical distribution. Median and mode are the same and the data is symmetrical.  [Ref: Normal distribution](https://en.wikipedia.org/wiki/Normal_distribution)In the above function, I have asked the numpy to return an array 10,000 random values and to return them in a normal probability distribution. I have called ```np.random.normal``` function with an argument which centres the values around 0, has a standard deviation of 1.0 and returns an array of 10,000 random vaues. The histograms tell you approximately how data is distributed throughout its range.**What is a poisson distribution?**A poisson distribution is discrete frequency distribution which gives the probability of a number of independent events occurring in a fixed time. It is only defined for integer values. For instance, we could apply it to monthly counts of rainy days. In this case, we must assume that the event of a rainy day occurs at a fixed monthly rate. The goal of fitting the data to the Poisson distribution is to find the fixed rate.  [Ref: Poisson distribution](https://www.packtpub.com/mapt/book/big_data_and_business_intelligence/9781785282287/3/ch03lvl1sec42/fitting-aggregated-counts-to-the-poisson-distribution)When the mean of a poisson distribution becomes large, it becomes similar to a normal distribution. **Poisson and Binomial Distributions**<jupyter_code># Import numpy
import numpy as np

# Import scipy
import scipy, scipy.stats as stats

# Import matplotlib
import matplotlib.pyplot as plt

# Import pylab
import pylab

# Plot the first of 2 plots using the random poisson function
plt.subplot(1, 2, 1)
## Adapted from: https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.poisson.html#numpy.random.poisson
samples = np.random.poisson(5, 10000)
count, bins, ignored = plt.hist(samples, 14, density=True)
plt.title("Poisson Distribution")

# Plot the second of 2 plots using the random binomial function
plt.subplot(1, 2, 2)
n = 10
p = 0.3
k = np.arange(0,21)
binomial = stats.binom.pmf(k, n, p)
pylab.plot(k, binomial, 'o-')
plt.title("Binomial Distribution")

# Output the results
plt.show()<jupyter_output><empty_output><jupyter_text>**What is a poisson distribution?**A poisson distribution is discrete frequency distribution which gives the probability of a number of independent events occurring in a fixed time. It is only defined for integer values. For instance, we could apply it to monthly counts of rainy days. In this case, we must assume that the event of a rainy day occurs at a fixed monthly rate. The goal of fitting the data to the Poisson distribution is to find the fixed rate. [Ref: Poisson distribution](https://www.packtpub.com/mapt/book/big_data_and_business_intelligence/9781785282287/3/ch03lvl1sec42/fitting-aggregated-counts-to-the-poisson-distribution)**What is a binomial distribution**A binomial distribution is a also a discrete. This is a frequency distribution of the possible number of successful outcomes in a given number of trials in each of which there is the same probability of success. [Ref: Binomial distribution](https://stattrek.com/probability-distributions/binomial.aspx)Suppose we flip a coin two times and count the number of heads (successes). The binomial random variable is the number of heads, which can take on values of 0, 1, or 2. The binomial distribution is presented below. [Ref: Binomial Distribution](https://stattrek.com/probability-distributions/binomial.aspx)![image.png](attachment:image.png)The difference between a poisson distribution and a binomial distribution is that while both measure the number of certain random events (or "successes") within a certain frame, the binomial is based on discrete events, while the poisson is based on continuous events. [Ref: Poisson v Binomial](https://math.stackexchange.com/questions/1050184/difference-between-poisson-and-binomial-distributions)<jupyter_code># Import numpy
import numpy as np

# Import scipy
import scipy, scipy.stats as stats

# Import matplotlib
import matplotlib.pyplot as plt

# Import pylab
import pylab

# Import curve fit
from scipy.optimize import curve_fit

# Plot the first of 2 plots using the random poisson function
plt.subplot(1, 2, 1)
## Adapted from: https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.poisson.html#numpy.random.poisson
samples = np.random.poisson(5, 10000)
count, bins, ignored = plt.hist(samples, 14, density=True)
plt.title("Poisson Distribution")

# Plot the first of 2 plots using the random poisson function
plt.subplot(1, 2, 2)

## Adapted from: https://plot.ly/matplotlib/exponential-fits/
# Define the function
def exponenial_func(x, a, b, c):
    return a*np.exp(-b*x)+c

# Set the variables
x = np.array([399.75, 989.25, 1578.75, 2168.25, 2757.75, 3347.25, 3936.75, 4526.25, 5115.75, 5705.25])
y = np.array([109,62,39,13,10,4,2,0,1,2])

popt, pcov = curve_fit(exponenial_func, x, y, p0=(1, 1e-6, 1))

xx = np.linspace(300, 6000, 1000)
yy = exponenial_func(xx, *popt)

# Output the results
plt.plot(x,y,'o', xx, yy)
pylab.title('Exponential Distribution')
ax = plt.gca()
fig = plt.gcf()<jupyter_output><empty_output><jupyter_text>**What is a poisson distribution?**A poisson distribution is discrete frequency distribution which gives the probability of a number of independent events occurring in a fixed time. It is only defined for integer values. For instance, we could apply it to monthly counts of rainy days. In this case, we must assume that the event of a rainy day occurs at a fixed monthly rate. The goal of fitting the data to the Poisson distribution is to find the fixed rate. [Ref: Poisson distribution](https://www.packtpub.com/mapt/book/big_data_and_business_intelligence/9781785282287/3/ch03lvl1sec42/fitting-aggregated-counts-to-the-poisson-distribution)**What is the exponential distribution?**Of all the probability distributions, the normal (Gaussian) distribution is maybe be the most important, because it applies to so many common phenomena. The second most important is probably the exponential distribution. In statistics, the exponential distribution is the probability distribution that describes the time between events in a Poisson point process, i.e., a process in which events occur continuously and independently at a constant average rate. [Ref: Exponential distribution](https://en.wikipedia.org/wiki/Exponential_distribution)The Poisson models the number of arrivals in a certain fixed time. It is a discrete distribution while the exponential distribution models the waiting time between consecutive arrivals. It is a continuous distribution.  [Ref: Poisson v Exponential distribution](https://math.stackexchange.com/questions/1110817/difference-between-poisson-and-exponential-distributions-in-the-context-of-client)  4. Expain the use of seeds in generating pseudorandom numbers.An important part of any simulation is the ability to generate random numbers. Numpy uses various routines in the random subpackage to generate pseudorandom numbers. It uses a particular algorithm, called the Mersenne Twister, to generate pseudorandom numbers. [Ref: The Mersenne Twister](https://en.wikipedia.org/wiki/Mersenne_Twister)As mentioned previously, computers can't really generate random numbers. They can at best generate seeemingly random numbers. These random numbers are deterministic as they are generated by by an algorithm (the Mersenne Twister). To get the most random numbers for each run, call numpy.random.seed() (without an argument). Numpy will then obtain a random number from /dev/urandom or its Windows analog or it will use the clock. If the random seed is not reset, different numbers appear with every call to the function.For various applications, you'll want to set the seed. By setting the seed, I'll be able to predict the random numbers outputted by my function every time I call it. This will be particularly useful for code testing pruposes. If you have code that uses random numbers that you want to debug, it can be very helpful to set the seed before each run so that the code does the same thing every time you run it. **.seed** See below two examples of random number generation using the .randn function. The .randn function generates a random floating point numbers on the fly from a normal distribution. In the below examples, I am calling the .rand function with an argument of 4. The output of each call to the .randn function is an array of 4 floating point numbers in an normal distribution. Each time I call the .randn function, the result is different each time. Therefore, I am unable to predict the random numbers by each call to the .randn function.<jupyter_code># Import numpy
import numpy as np
np.random.randn(4)
import numpy as np
np.random.randn(4)<jupyter_output><empty_output><jupyter_text>However, if I introduce the .seed function, this makes the predictaion of the random nummbers far more easy to predict. In the below two examples, I am calling the .seed function with an argument of 42. After seeting the seed, the position I am now going to start with is 42. From then on, the random numbers that are generated are based on that same seed. I can now predict the numbers that will generate from the .randn function. The below two snippets of code demonstrate, the output of each call to .randn function will be the same every time I run it.<jupyter_code>import numpy as np
np.random.seed(42)
np.random.randn(4)
import numpy as np
np.random.seed(42)
np.random.randn(4)<jupyter_output><empty_output><jupyter_text>**.RandomState**The .RandomState function is similar to the .seed function and will produce the same results. However, when using the .RandomState function, you must save an instance of the class initiated wth a seed. In the below example, I am doing this with the following piece of code. ```rng = np.random.RandomState(42)``By saving an instance of the class each time I call the function, I can predict the random numbers generated each time. See the below 2 examples of this. [Ref: RandomState](https://stackoverflow.com/questions/22994423/difference-between-np-random-seed-and-np-random-randomstate)<jupyter_code>import numpy as np
rng = np.random.RandomState(42)
rng.randn(4)
import numpy as np
rng2 = np.random.RandomState(42)
rng2.randn(4)<jupyter_output><empty_output><jupyter_text>See the below two examples, I have not used the .RandomState function to save an instance of the class initiated with a seed. Each time I make a call to .randn function, different random numbers are generated each time. Therefore, I am unable to predict what random numbers will be generated.<jupyter_code>import numpy as np
np.random.randn(4)
import numpy as np
np.random.randn(4)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.07439411998410807, 'fraction_numerical': 0.019169646404449743, 'mean_word_length': 5.231689704972148, 'pattern_counts': {'":': 0, '<': 72, '<?xml version=': 0, '>': 72, 'https://': 56, 'lorem ipsum': 0, 'www.': 16, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '18', 'dir': 'jupyter-structured-clean-dedup', 'id': '585831', 'license': 'MIT', 'n_tokens_mistral': 8558, 'n_tokens_neox': 7908, 'n_words': 3624, 'path': 'numpy-random.ipynb', 'repo_name': 'fionanealon/numpy-random', 'size': '30204'}