Search code examples
pythonsamplingurn

Draw 2 numbers from urn with replacement - Python


my urn contains the numbers 1.3 and 0.9, which I would like to draw 35 times per simulation with replacement. Then perform a final calculation, from which the result is appended to a list. In total I would like to perform 10000 simulations.

My code looks like this:

#Draw either 1.3 or 0.9
returns = [1.3,0.9]

#No. of simulations
simulations = 10000

#10000 for loops
for i in range(simulations):
    lst = []

    #each iteration should include 35 random draws with replacement
    for i in range(35):
        lst.append(random.choices(returns,1))
        
    lst = np.array(lst)

#Do final calculation and append solution to list
ret = []
ret.append((prod(lst)^(1/35))-1)

The error i receive is TypeError: 'int' object is not iterable. I understand why it's not working as i am trying to convert an integer to a list object....but i just don't know how to solve this?

Full stack trace:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-15-5d61655781f6> in <module>
      9     #each iteration should include 35 random draws with replacement
     10     for i in range(35):
---> 11         lst.append(random.choices(returns,1))
     12 
     13     lst = np.array(lst)

~/opt/anaconda3/lib/python3.7/random.py in choices(self, population, weights, cum_weights, k)
    355                 total = len(population)
    356                 return [population[_int(random() * total)] for i in range(k)]
--> 357             cum_weights = list(_itertools.accumulate(weights))
    358         elif weights is not None:
    359             raise TypeError('Cannot specify both weights and cumulative weights')

TypeError: 'int' object is not iterable

Solution

  • If you want to convert lst to a numpy array, you can instead use numpy.random.choice. This will also remove the need of the for loop.

    import numpy as np
    #Draw either 1.3 or 0.9
    urn = [1.3,0.9]
    
    #No. of simulations
    simulations = 10000
    
    #No. of draws
    draws = 35
    
    # simulate the draws from the urn
    X=np.random.choice(urn,(draws,simulations))
    
    # print first 10 elements as a check
    print(X[1:10])
    
    # print shape as a check
    print(X.shape)
    
    

    output:

    [[1.3 1.3 1.3 ... 0.9 1.3 1.3]
     [0.9 1.3 0.9 ... 0.9 0.9 0.9]
     [0.9 1.3 0.9 ... 1.3 1.3 0.9]
     ...
     [1.3 0.9 0.9 ... 1.3 0.9 0.9]
     [1.3 1.3 1.3 ... 0.9 0.9 1.3]
     [1.3 1.3 0.9 ... 0.9 1.3 1.3]]
    (35, 10000)
    

    I changed the name of returns to urn. returns is a bit confusing in python.