Используя Python 3.7.3, случайным образом выбирайте / выбирайте из взвешенного списка файлов в данном каталоге - PullRequest
2 голосов
/ 02 июля 2019

Используя Python 3.7.3, мне нужно случайным образом выбирать из взвешенного списка файлов в данном каталоге.Веса определяются тем, насколько новым является файл, и пометил ли пользователь как избранное (чем новее файл, тем чаще он выбирается).

Какой самый эффективный способ установить вес?Я хочу, чтобы поведение моего распределения случайно выбранных элементов было таким же, как распределение весов в списке.Флаг избранного будет сохранен в словаре с именами файлов в качестве ключа и true / false в качестве значения.

Предположим, что количество элементов в списке весов должно равняться количеству элементов в filesList,и что список весов должен все вместе составлять 1. Кроме того, это выполняется на Raspberry Pi 3/4.

Если другой метод лучше, чем numpy.random.choice, я все за него.

Я изучил Случайный выбор элемента из взвешенного списка .

import numpy, collections

#filesList = os.listdir('./assets')    

filesList= ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'] 

count = len(filesList)

Favorites = {}
for key in Listy:
    Favorites[key] = random.choice([True, False])

weights = [   0.01666666666666667,
0.02666666666666667,
0.03666666666666667,
0.04666666666666667,
0.05666666666666667,
0.06666666666666667,
0.06666666666666667,
0.06666666666666667,
0.06666666666666667,
0.06666666666666667,
0.07666666666666667,
0.08666666666666667,
0.09666666666666667,
0.10666666666666667,
0.11666666666666667]

# Currently the code for setting the weights is commented out, as I'm not sure how to do it. Above is an example of distribution. 

#weights = [0 for x in range(count)]
#for x in range(count):
#    #offset = ?
#    weights[x-1] = 1/count #+ offset


print(f'Favorites: {Favorites}')
print('weights', weights)    

sum = 0     #sum of all weight values must be 1
for weight in weights:
    sum += weight

print(f'sum of weights: {sum}')

l = [numpy.random.choice(filesList, p=weights) for _ in range(10000)]

print(f'Results: {collections.Counter(l)}')

1 Ответ

3 голосов
/ 02 июля 2019

Начиная с Python 3.6, существует random.choices () , который принимает веса.

Веса не должны быть нормализованы, то есть они не должны суммироватьсядо 1.

import random

choices = random.choices(filesList, weights=weights)
print(choices[0])

РЕДАКТИРОВАТЬ: Теперь, когда я понял, что вопрос о фактических весах, некоторые предложения.Для каждого файла вычислите такой вес:

def compute_weight(age_in_days, favorite):
    age_factor = 1 #set to how much you want age to matter
    favorite_factor = 1 #set how much you want the favorite to matter
    if favorite:
        return math.exp(-age_in_days*age_factor) * (favorite_factor+1)
    else:
        return math.exp(-age_in_days*age_factor)

или что-то подобное.Возможно, добавьте favorite_factor вместо умножения, просто поиграйте с ним.

...