Generating a random value for each user, then sorting according to this value
How about doing a first pass where you generate, for each user, a random number from a Gaussian distribution with mean actual_rating? Then you sort according to this random number instead of sorting according to actual_rating directly.
stddev = 1.0 # the larger this number, the more shuffled the list - the smaller, the more sorted the list
sorted_users = sorted(users, key=lambda u:np.random.normal(u.actual_rating, stddev))
Note the parameter stddev
which you can adjust to suit your needs. The higher this parameter, the more shuffled the list in the end.
Sorting the list, then shuffling it lightly
Inspired by How to lightly shuffle a list in python?
Sort the list according to actual_rating
, then shuffle it lightly.
sorted_users = sorted(users, key=lambda u:u.actual_rating)
nb_passes = 3
proba_swap = 0.25
for k in range(nb_passes):
for i in range(k%2, len(sorted_users) - 1, 2):
if random() < proba_swap:
sorted_users[i], sorted_users[i+1] = sorted_users[i+1], sorted_users[i]
Note the two parameters nb_passes
(positive integer) and proba_swap
(between 0.0 and 1.0) which you can adjust to better suit your needs.
Instead of using a fixed parameter proba_swap
, you could make up a formula for a probability of swapping that depends on how close the actual_ratings of the two users are, for instance def proba_swap(r1,r2): return math.exp(-a*(r1-r2)**2)/2.0
for some positive parameter a
.
Or alternatively:
sorted_users = sorted(users, key=lambda u:u.actual_rating)
nb_swaps = int(1.5 * len(sorted_users)) # parameter to experiment with
for i in random.choices(range(len(sorted_users)-1), k=nb_swaps):
sorted_users[i], sorted_users[i+1] = sorted_users[i+1], sorted_users[i]
See also
After searching a little bit, I found this similar question: