Создайте список случайных чисел и отфильтруйте список, чтобы номера были больше 50 - PullRequest
3 голосов
/ 16 октября 2019

Я использую списки для создания списка случайных чисел с numpy. Есть ли способ проверить, является ли генерируемое случайное число больше 50, и только затем добавить его в список.

Я знаю, что могу просто использовать:

numbers = [np.random.randint(50,100) for x in range(100)]

, и это решиловопрос, но я просто хочу знать, возможно ли каким-то образом проверить, генерирует ли np.random.randint (1100) число больше 50

Что-то вроде

numbers = [np.random.randint(1,100) for x in range(100) if {statement}]

Поскольку сравнивается np.random.randit генерирует другое число, которое не совпадает с первым.

Я просто хочу знать, есть ли возможность отфильтровать сгенерированные числа перед добавлением их в список.

Ответы [ 9 ]

4 голосов
/ 16 октября 2019

Вы используете numpy, поэтому мы можем использовать метод индексации.

my_array = np.random.randint(1, 100, size=100)
mask = my_array > 50
print(my_array[mask]) # Contain only value greater than 50

Но, конечно, лучший способ сделать то, что вы хотите, это.

results = np.random.randint(51,100, size=100)
# If you really need a list
results_list = results.tolist()

Пожалуйста, не зацикливайтесь на массиве в целом.

Редактировать: заменить my_list на my_array на основе комментария @ norok2.

Edit2: соображения скорости

Numpy

С маской

%%timeit
my_array = np.random.randint(1, 100, size=100)
mask = my_array > 50
my_array[mask]

5,31 мкс ± 127 нс на цикл (среднее ± стандартное отклонение из 7 циклов, по 100000 циклов каждый)

10 000 000 элементов:

1 циклЛучшее из 3: 198 мс на цикл

С нулевым значением (@Severin Pappadeux anwser)

%%timeit
q = np.random.randint(1, 100, 1000)
m = np.where(q > 50)
q[m]

20,9 мкс ± 663 нс на цикл (среднее ± стандартное отклонениеДевять циклов, по 10000 циклов в каждом)

10 000 000 элементов:

1 цикл, лучшее из 3: 196 мс на цикл

Pure Python

Часть ответа @Alexander Cécile

%%timeit
rand_nums = (random.randint(0, 99) for _ in range(10))
arr = [val for val in rand_nums if val > 50]

19,4 мкс ± 1,99 мкс на цикл (среднее ± стандартное отклонение из 7 прогонов, 10000 петель каждый)

10 000 000 элементов:

1 цикл, лучшее из 3: 11,4 с на цикл

Смешать NumPy и список

@ DrBwts answer

%%timeit
number = [x for x in np.random.randint(1, high=100, size=100) if x > 50]

28,9 мкс ± 1,52 мксза цикл (среднее ± стандартноедевиацияиз 7 циклов, по 10000 циклов в каждом)

10 000 000 элементов:

1 цикл, лучшее из 3: 2,76 с на цикл

@makis answer

%%timeit 
numbers = [x for x in (np.random.randint(1,100) for iter in range(100)) if x > 50]

164 мкс ± 19,4 мкс на цикл (среднее ± стандартное отклонение из 7 циклов, по 10000 циклов каждый)

10 000 000 элементов:

1 цикл, лучшее из 3: 12,2 с на цикл

@ Ромеро Валентайн ответ

rand = filter(lambda x: x>50, np.random.randint(1,100,100))
rand_list = list(rand)

35,9 мкс ± 1,97 мкс на цикл(среднее ± стандартное отклонение из 7 прогонов, 10000 циклов каждый)

10 000 000 элементов:

1 цикл, лучшее из 3: 3,41 с на цикл

Выводы

  • Для простых задач все эти методы хороши.
  • На больших массивах numpy подавляет конкуренцию.

Ответы, предоставляющие дополнительную информацию

  • @ norok2
  • @ Alexander Cécile
2 голосов
/ 16 октября 2019

В вашем вопросе у вас есть некоторый код:

numbers = [np.random.randint(50, 100) for x in range(100)]

, который, вероятно, должен быть

numbers = np.random.randint(50, 100, 100)

Затем вы спрашиваете, существует ли способ повторить это, используя list-понимание в сочетании с фильтрацией, начиная с чего-то вроде:

numbers = [np.random.randint(1, 100) for x in range(100) if ...]

Ответ на этот вопрос, как правило, NO .

Причина в том, чтоСинтаксис фильтрации условий будет действовать как фильтр для сгенерированных чисел, после числа будут сгенерированы и предварительно получены.

Поэтому, хотя код [np.random.randint(50,100) for x in range(100)] будет генерировать 100 элементов, любой методна основе фильтрации понимания или даже явного использования filter() будет иметь неизвестное количество элементов (обычно меньше 100, в зависимости от того, сколько элементов соответствует указанному условию).

Чтобы достичь этого уровня контроляВы можете использовать генератор на основе while (который не может быть включен в понимание ), например:

import numpy as np


def my_brand_new_generator(n, a=1, b=100):
    i = 0
    while i < n:
        x = np.random.randint(a, b)
        if x > 50:
            yield x
            i += 1


numbers = list(my_brand_new_generator(100))
print(numbers[10])
# [94 97 50 53 53 89 59 69 71 86]

print(len(numbers))
# 100

Для контраста:

numbers = [x for x in (np.random.randint(1,100) for iter in range(100)) if x > 50]
print(len(numbers))
# 54

x = np.random.randint(1, 100, 100)
numbers = x[x > 50]
print(len(numbers))
# 43

В качестве примечанияs:

  • * my_brand_new_generator() следует рассматривать только как пример toy , чтобы проиллюстрировать вышеупомянутую идею.
  • в целом NumPy предлагает лучшие альтернативы явной итерацииПоэтому, если возможно, используйте , что .
  • для генерации одного случайного целого числа, вы можете использовать random.randint() из стандартной библиотеки Python.
1 голос
/ 16 октября 2019

Будьте осторожны, чтобы не смешивать numpy и обычный питон, когда у вас нет причин! Вы пишете, что можете использовать numbers = [np.random.randint(50,100) for x in range(100)], но было бы лучше просто сделать np.random.randint(low=50, high=100, size=100), чтобы создать массив из 100 случайных чисел.

Вот чистое решение Python:

import random

rand_nums = (random.randint(0, 99) for _ in range(10))
arr = [val for val in rand_nums if val > 50]

Который, очевидно, можно записать одной строкой:

arr = [val for val in (random.randint(0, 99) for _ in range(10)) if val > 50]

А вот решение для кучи:

import numpy as np

arr = np.random.randint(low=0, high=100, size=10)
arr = arr[arr > 50]
1 голос
/ 16 октября 2019

@ FlorianBernard прав, НЕ смешивайте списки Python и массивы NumPy. Оставайтесь в мире NumPy, все будет быстрее в любом случае. В NumPy нет эквивалента для понимания списков Python, поскольку он работает с массивами, а не с отдельными элементами один за другим.

В любом случае, существует более сложная, но более мощная альтернатива ответу @FlorianBernard, использующий numpy.where функция

Fe, она позволяет объединять фильтрованные и базовые массивы в новый. Простой код для начала с

import numpy as np
q = np.random.randint(1, 100, 1000)
m = np.where(q > 50)
print(q[m])
1 голос
/ 16 октября 2019

Да, это возможно, сначала сгенерируйте ваши 100 чисел (или сколько вам нужно) между 1 и 100 здесь, но опять-таки это ваше дело, затем итерируйте их, проверяя каждое и сохраняя только те, которые превышают 50 ...

y = np.random.randint(1, high=100, size=100)
number = [x for x in y if x > 50]

Альтернативно в одну строку ...

number = [x for x in np.random.randint(1, high=100, size=100) if x > 50]
0 голосов
/ 16 октября 2019
import random
ml=random.sample(range(100),100)


# Get list of items larger than 50 using list comprehension approach
filtered = [x for x in ml if x > 50]
print(filtered)


# Get list of items larger than 50 using filter approach
filtered = list(filter(lambda x: x > 50, ml))
print(filtered)
0 голосов
/ 16 октября 2019

Просто используйте функцию filter:

rand = filter(lambda x: x>50, np.random.randint(1,100,100))
rand_list = list(rand)

Нет необходимости в понимании списка.

0 голосов
/ 16 октября 2019

Обманите его, создав рекурсивную функцию, которая будет раскручиваться, только если число больше 50.

import numpy as np

def genrandx():
    # Using a function allows you do to all sorts of crazy stuff and checks.
    x = np.random.randint(1,100)
    x = int((x*.5)**2)
    if (
        (x > 50) and
        (x < 1000) and 
        ( (x%3 == 0) or (x%3 == 0) )
       ): 
        return x 
    else: 
        return genrandx() 

numbers = [ genrandx() for x in range(100)]
print("({}){}".format(len(numbers), numbers))

ВЫХОД:

(100)[930, 729, 306, 576, 600, 225, 324, 324, 462, 324, 462, 756, 324, 225, 702, 552, 576, 72, 81, 900, 600, 225, 930, 900, 576, 240, 552, 702, 441, 72, 462, 132, 144, 324, 72, 702, 462, 930, 72, 306, 240, 225, 870, 210, 729, 600, 420, 132, 240, 420, 441, 420, 72, 756, 225, 900, 72, 90, 72, 600, 72, 420, 210, 702, 240, 462, 600, 156, 81, 900, 144, 72, 225, 324, 144, 420, 600, 576, 729, 156, 900, 81, 756, 729, 702, 90, 462, 306, 600, 930, 729, 240, 552, 144, 90, 900, 420, 225, 600, 156]
0 голосов
/ 16 октября 2019

Использование

numbers = [x for x in (np.random.randint(1,100) for iter in range(100)) if x > 50]

Шаг 1: (np.random.randint(1,100) for iter in range(100)): генерируется 100 раз, случайное целое число от 1 до 100.

Шаг 2: if x > 50: генерируется числов сравнении. Если это> 50, он проходит и добавляется в список.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...