Я думаю, что было бы быстрее вытащить все хорошие значения, а затем использовать random.choice()
, чтобы выбрать один, когда вам это нужно.Примерно так:
import numpy as np
import random
from itertools import izip
data = np.random.normal(0, 1, (10, 100))
for row in data:
good_ones = np.logical_and(row >= -0.8, row <= 0.8)
good = row[good_ones]
row_copy = np.array([x if f else random.choice(good) for f, x in izip(good_ones, row)])
Высокоуровневый код Python, который вы пишете, работает медленнее, чем внутренние компоненты языка Python.Если вы можете протолкнуть работу внутрь C, это обычно быстрее.Другими словами, постарайтесь позволить Python выполнять тяжелую работу за вас, а не писать много кода.Это дзен ... писать меньше кода, чтобы получить более быстрый код.
Я добавил цикл, чтобы выполнить ваш код 1000 раз, и выполнить мой код 1000 раз, и измерил, сколько времени они потребовали для выполнения.Согласно моему тесту, мой код работает в десять раз быстрее.
Дополнительное объяснение того, что делает этот код:
row_copy
устанавливается путем создания нового списка и последующего вызова np.array()
в новом списке, чтобы преобразовать его в объект массива NumPy.Новый список строится на основе понимания списка.
Новый список составляется по правилу: если число хорошее, сохраните его;иначе, сделайте случайный выбор из числа хороших значений.
Понимание списка проходит по последовательности значений, но для применения этого правила нам нужно два значения: число и флагговоря, хорошо это число или нет.Самый простой и быстрый способ сделать так, чтобы понимание списка проходило по двум последовательностям одновременно, это использовать izip()
, чтобы "сжать" две последовательности вместе.izip()
выдаст кортежи по одному, где кортеж равен (f, x)
;f
в этом случае - флаг, говорящий «хорошо» или «нет», а x
- число.(Python имеет встроенную функцию под названием zip()
, которая делает почти то же самое, но фактически создает список кортежей; izip()
просто создает итератор, который выдает значения кортежей. Но вы можете играть с zip()
вприглашение Python, чтобы узнать больше о том, как это работает.)
В Python мы можем распаковать кортеж в имена переменных следующим образом:
a, b = (2, 3)
В этом примере мы устанавливаем a
в2 и b
до 3. В понимании списка мы распаковываем кортежи из izip()
в переменные f
и x
.
Тогда ядром понимания списка является оператор "ternary if"например так:
a if flag else b
Вышеприведенное вернет значение a
, если значение flag
равно true, а в противном случае вернет b
.Единственное в этом списке:
x if f else random.choice(good)
Это реализует наше правило.