Simulations in Python


Simulations are useful for simulating events many times without actually doing them. By using python libraries such as random, we can analyze the outcomes and behavior of these events in a virtual setting, saving us the trouble from tedious experiments.

For example, what should we do if we want to get the power of three for a range of numbers? It would be too tedious to calculate this one by one. By introducing a for loop, declaring a placeholder variable 'i', and computing the power of three raised to the value of 'i', we can skillfully simplify this task to a few lines of code. Additionally, by putting the outcome into a dataframe, we can enhance clearity and facilitate better analysis.

The overall structure is as follows:

  1. Initializing an empty list: We start by creating an empty list named data, so that we can store the data inside.

  2. Iterating through a range: We utilize a for loop to iterate through a specific number of times. In this case, we input the argument 10 into range() for simplicity, so the loop variable 'i' will range from 0 to 9.

  3. Appending data to the list: We append the calculated power of 3 to the data list as a dictionary with the key 'power' and the corresponding value.

  4. Transforming the list into a DataFrame: After all data is collected, we exit the for loop and transform the list data into a DataFrame using the pd.DataFrame() function from the Pandas library.

import pandas as pd
# Create a for loop that appends text to a list, and then transform the list into a dataframe
data = [] # Initialize an empty list to store the data
for i in range(10): # Loop for 10 times
    data.append({"power": 3**i})  # Calculate the power of 3 raised to the ith exponent and append it as a dictionary 
df = pd.DataFrame(data)
df
power
01
13
29
327
481
5243
6729
72187
86561
919683
For Loop Example

A detailed explanation of for loops can be found as follows:

Random library

The random library is very useful because it allows us to generate random numbers, sample elements from certain distribution or population, shuffle the whole array, and so on! Below is a highly concise showcase of some basic functions in random library.

import random
my_list = [1, 2, 3, 4, 5, 6]
random.shuffle(my_list) # shuffle the list
print("Shuffled list:", my_list)
random_element = random.choice(my_list) # choose a random element from the list
print("Random element:", random_element)
random_sample = random.sample(my_list, 3) # choose three random elements from the list
print("Random sample:", random_sample)

Shuffled list: [3, 2, 4, 6, 5, 1]
Random element: 6
Random sample: [6, 2, 3]

Random Library

A more detailed explanation of random library can be found as follows:

For example, let's generate a random integer from 1 to 6 ten times and see the results:

data = []
for i in range(10):
    data.append(random.randint(1,6)) # Returns a random number between 1 to 6
df = pd.DataFrame(data)
df
0
03
12
25
34
44
53
66
75
84
93
```
Random Library Example

By calling the randint function of random, we can generate an integer in a specified range, which is 1-6 in this case. Each iteration of the loop will generate a random number between 1 and 6 and append it to data, allowing us to simulate random events such as rolling a die or flipping a coin.

If we run this code cell again, the result will be different than the first time:

data = []
for i in range(10):
    data.append(random.randint(1,6))
df = pd.DataFrame(data)
df
0
06
16
25
31
45
56
61
71
83
93
```
Random Results

Simple Simulations (Die Roll)

What we did above was basically how to create a simulation for rolling a die! We just need to add a few more elements, such as the column name, and we will have created our first simulation.

Let's simulate rolling a six-sided die 50 times:

# Rolling a die 50 times
data = []
for i in range (50):
    roll = random.randint(1,6)
    d = {"roll" : roll}
    data.append(d)
df = pd.DataFrame(data)
df
roll
03
11
22
31
41
56
65
71
82
91
104
113
124
134
143
152
161
176
183
192
205
215
223
235
244
256
263
275
281
295
301
315
325
332
342
353
363
375
381
396
402
412
424
434
442
454
466
473
486
492
```
Simulating a die roll

Here, we created a column called roll, attached the integer of our die roll to it, and added it to data in each iteration. This way, the columns of the simulation can have meaningful names and help you understand the simulation better.

Simple Simulations (Coin Toss)

We can also simulate events where the outcome for each iteration is not a number. For this we will have to use random.choice.

# coin toss 10 times
data = []
for i in range (10):
    flip = random.choice(["heads", "tails"])
    d = {"flip" : flip}
    data.append(d)
df = pd.DataFrame(data)
df
flip
0heads
1heads
2heads
3tails
4tails
5heads
6heads
7tails
8tails
9heads
```
Simulating a coin toss

random.choice allows us to choose from a list, in this case between heads and tails. We can add more into the list if we wanted to simulate other events with more possible outcomes.

Simulations with Conditionals

Imagine a game where a random integer between 1 and 10 is rolled and you win if the outcome is a 7. It can be simulated using the following code. From the dataframe, all the available result is surprisingly a "lose". Since the probability of winning in each trail is 0.1, this is totally feasible and a likely outcome.

# Simulating a game where a random integer between 1 and 10 is rolled.
# If the rolled number is 7, the outcome is "win"; otherwise, it's "lose".
data = []
for i in range(10):
    roll = random.randint(1, 10) # Generate a random integer between 1 and 10 (inclusive)
    if roll == 7: # if the outcome is a seven, you wins!
        outcome = "win"
    else: # otherwise you lose
        outcome = "lose"
    data.append({"outcome": outcome}) # Store the outcome as a dictionary and append it to the list
df = pd.DataFrame(data) 
df
outcome
0lose
1lose
2lose
3lose
4lose
5lose
6lose
7lose
8lose
9lose
```
Simulating with Conditionals

Complex Simulations (One-Dimension Random Walk)

Random walk describes a path consisting of a series of random steps. In its simplest form, a one-dimensional random walk takes place on a straight line. At each step, the walker moves either to the left or to the right with equal probability of 0.5. Additionally, position of the walker after each step is determined only by the previous position, also known as the memoryless property. Mathematically, if $x_i$ represents the position of the walker after $i$ steps, then $x_i=x_i−1+ϵ_i$, where $ϵ_i$ is a random variable representing the step taken at step $i$. Random walk is a extremely simple case of Markov Property and Stochastic Process.

data = []
current_value = 0
for i in range(100):
    step = random.choice([-1, 1]) # equal probability of getting up and down
    current_value += step
    data.append(current_value)
df = pd.DataFrame(data, columns=['Time'])
df

Time
01
12
21
30
41
......
954
965
976
985
994

100 rows × 1 columns

```
One-Dimension Random Walk
To make a more vivid, we can plot the following graph.
import matplotlib.pyplot as plt
plt.plot(df)
plt.xlabel('Step')
plt.ylabel('Value')
plt.title('Random Walk')
plt.show()
Random Walk Line Chart
Photo showing a new CSV file

Complex Simulations (Drawing Poker Card with Replacement)

Let's simulate drawing 20 cards with replacement from a standard deck of 52 playing cards. Each card has a suit (hearts, diamonds, clubs, or spades) and a rank (2 to 10, plus Jack, Queen, King, Ace). Since each individual card can be expressed by a suit and a rank, we'll randomly select one suit and one rank for each draw. Therefore, we can come up with the following simulation:

# simulation to select 20 cards from a standard 52 card deck with replacement
data = []
for i in range(20):
  rank = random.choice(['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'])
  suit = random.choice(['heart', 'diamond', 'spade', 'club'])
  d = { "rank" : rank, "suit" : suit}
  data.append(d)
df = pd.DataFrame(data)
df
ranksuit
0Qdiamond
19club
28spade
34club
46spade
53spade
6Aclub
76spade
88diamond
94diamond
107club
112club
128heart
13Kspade
144heart
156spade
1610heart
1710club
187club
192diamond
```
Simulating drawing a Card

Additional explanations for simple simulations can be found here:

Python Documentation

Click Here for the full python documentation for random.