Search code examples
pythonrandomprobability

Place 2 values randomly in array with certain probability


I wanted to create a random array with the lenght of 24 in python, by assigning the values of a list seq=[30,170]. So I wanted to have an array which looks like a=[30,30,30,170,30,170,...]. The problem is, that the values shouldn't be assigned completely random, but with a certain probability. In this case, if the first value is 30 (or 170) the probability of the next value to be 30 (or 170) as well, should be 90% and the probability of the next value to be 170 (or 30) should be 10%.

Does anyone know how to do this? For the moment I only found how to arrange them randomly. Thanks!!

import random
seq=[30,170] 
a = random.choices(seq,k=24) 

Solution

  • You can provide weights to random.choices(population, weights=None, *, cum_weights=None, k=1).

    You need to do it iteratively to be able to reference the last value when looking up weight you need to use:

    import random
    
    seq = [30, 170] 
    
    # weight lookup
    wgt = {30: (90, 10), 170:(10, 90)}
    
    r = []
    
    for _ in range(24):
        if not r:
            # need some initial value: 50/50
            r.append(random.choice(seq))
        else:          
            # k == 1, using correct weights from lookup, use only single value and add it
            r.append(random.choices(seq, weights=wgt[r[-1]], k=1)[0])
    
    print(r)
    

    Output over 8 runs:

    [170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170]
    
    [30, 30, 30, 30, 30, 30, 170, 170, 170, 170, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]
    
    [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]
    
    [30, 30, 30, 30, 30, 170, 170, 170, 170, 170, 170, 170, 170, 30, 30, 170, 170, 170, 170, 170, 170, 170, 170, 170]
    
    [170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 30, 30, 30, 170, 170, 170, 170]
    
    [170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 30, 30, 30, 30, 30, 30, 30, 30, 30]
    
    [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]
    
    [30, 30, 170, 170, 30, 170, 170, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]
    

    You can also provide the weighting yourself:

    seq = [30,170]
    w = {30: (30,30,30,30,30,30,30,30,30,170),           # if  30: use 9 * 30 + 1 * 170
         170:(30,170,170,170,170,170,170,170,170,170)}   # if 170: use 9 * 170 + 1 * 30
    
    r = []
    for _ in range(24):
        if not r:
            r.append(random.choice(seq))
        else:          
            r.append(random.choice(w[r[-1]]))