Генерация случайного массива numpy из заданного списка элементов, по крайней мере, с одним повторением каждого элемента - PullRequest
0 голосов
/ 25 декабря 2018

Я хочу создать массив (скажем, output_list) из заданного numpy (скажем, input_list) после повторной выборки так, чтобы каждый элемент из input_list существовал в output_list хотя бы один раз.Длина output_list всегда будет> длиной input_list.

Я пробовал несколько подходов, и я ищу более быстрый метод.К сожалению, numpy random.choice не гарантирует, что хотя бы один элемент существует.

Шаг 1: Генерация данных

import string
import random
import numpy as np

size = 150000
chars = string.digits + string.ascii_lowercase
input_list= [
            "".join(
                [random.choice(chars) for i in range(5)]
            ) for j in range(dict_data[1]['unique_len'])]

Вариант 1: Давайте попробуем numpy 'random.choice с равномерным распределением в терминахвероятности.

output_list = np.random.choice(
    input_list,
    size=output_size,
    replace=True,
    p=[1/input_list.__len__()]*input_list.__len__()
    )
assert set(input_list).__len__()==set(output_list).__len__(),\
    "Output list has fewer elements than input list"

Это вызывает утверждение:

В списке вывода меньше элементов, чем в списке ввода

Опция 2 Давайте добавим случайные числа к input_list и затем перемешаем их.

output_list = np.concatenate((np.array(input_list),np.random.choice(
    input_list,
    size=output_size-input_list.__len__(),
    replace=True,
    p=[1/input_list.__len__()]*input_list.__len__()
)),axis=None)

np.random.shuffle(output_list)
assert set(input_list).__len__()==set(output_list).__len__(),\
    "Output list has fewer elements than input list"

Хотя это не вызывает никаких утверждений, я ищу более быстрое решение, чем это, либо алгоритмически, либо с использованием встроенной функции numpy.

Спасибо за любую помощь.

1 Ответ

0 голосов
/ 25 декабря 2018

Пусть lenI - длина входного списка, lenO - длина выходного списка.

1) Выполните lenO - lenI итераций равномерного случайного выбора из списка источников

2) Затем добавьтевсе входные списки в конце выходного списка

3) Затем выполните lenI итераций перемешивания Фишера-Йейтса для равномерного распределения последних элементов.

import random
src = [1, 2, 3, 4]
lD = 10
lS = len(src)
dst = []
for _ in range(lD - lS):
    dst.append(src[random.randint(0, lS-1)])
dst.extend(src)
print(dst)
for i in range(lD - 1, lD - lS - 1, -1):
    r = random.randint(0, lD - 1)
    dst[r], dst[i] = dst[i], dst[r]
print(dst)

>>[4, 3, 1, 3, 4, 3, 1, 2, 3, 4]
>>[4, 3, 1, 3, 4, 3, 1, 3, 4, 2]

Это подход с линейной сложностью.

...