У меня есть следующий код:
r = numpy.zeros(shape = (width, height, 9))
Создает матрицу width x height x 9
, заполненную нулями. Вместо этого я хотел бы знать, есть ли функция или способ инициализировать их вместо этого NaN
простым способом.
У меня есть следующий код:
r = numpy.zeros(shape = (width, height, 9))
Создает матрицу width x height x 9
, заполненную нулями. Вместо этого я хотел бы знать, есть ли функция или способ инициализировать их вместо этого NaN
простым способом.
Вам редко нужны циклы для векторных операций в numpy. Вы можете создать неинициализированный массив и назначить сразу все записи:
>>> a = numpy.empty((3,3,))
>>> a[:] = numpy.nan
>>> a
array([[ NaN, NaN, NaN],
[ NaN, NaN, NaN],
[ NaN, NaN, NaN]])
Я приурочил альтернативы a[:] = numpy.nan
здесь и a.fill(numpy.nan)
как опубликовано Blaenk:
$ python -mtimeit "import numpy as np; a = np.empty((100,100));" "a.fill(np.nan)"
10000 loops, best of 3: 54.3 usec per loop
$ python -mtimeit "import numpy as np; a = np.empty((100,100));" "a[:] = np.nan"
10000 loops, best of 3: 88.8 usec per loop
Тайминги предпочитают ndarray.fill(..)
как более быструю альтернативу. OTOH, мне нравится реализация удобства numpy, где вы можете назначать значения целым фрагментам в то время, намерение кода очень ясно.
Другой вариант - использовать numpy.full
, параметр, доступный в NumPy 1. 8+
a = np.full([height, width, 9], np.nan)
Это довольно гибкий способ, и вы можете заполнить его любым другим номером.
Я сравнил предложенные альтернативы по скорости и обнаружил, что для заполнения достаточно больших векторов/матриц все альтернативы, кроме val * ones
и array(n * [val])
, одинаково быстры.
Код для воспроизведения сюжета:
import numpy
import perfplot
val = 42.0
def fill(n):
a = numpy.empty(n)
a.fill(val)
return a
def colon(n):
a = numpy.empty(n)
a[:] = val
return a
def full(n):
return numpy.full(n, val)
def ones_times(n):
return val * numpy.ones(n)
def list(n):
return numpy.array(n * [val])
perfplot.show(
setup=lambda n: n,
kernels=[fill, colon, full, ones_times, list],
n_range=[2**k for k in range(20)],
logx=True,
logy=True,
xlabel='len(a)'
)
Вы знакомы с numpy.nan
?
Вы можете создать свой собственный метод, например:
def nans(shape, dtype=float):
a = numpy.empty(shape, dtype)
a.fill(numpy.nan)
return a
Тогда
nans([3,4])
выводит
array([[ NaN, NaN, NaN, NaN],
[ NaN, NaN, NaN, NaN],
[ NaN, NaN, NaN, NaN]])
Я нашел этот код в списке рассылки.
Вы всегда можете использовать умножение, если не сразу вспомните методы .empty
или .full
:
>>> np.nan * np.ones(shape=(3,2))
array([[ nan, nan],
[ nan, nan],
[ nan, nan]])
Конечно, он работает и с любым другим численным значением:
>>> 42 * np.ones(shape=(3,2))
array([[ 42, 42],
[ 42, 42],
[ 42, 42]])
Но принятый ответ @u0b34a0f6ae был в 3 раза быстрее (циклы CPU, а не циклы мозгов, чтобы запомнить синтаксис numpy;):
$ python -mtimeit "import numpy as np; X = np.empty((100,100));" "X[:] = np.nan;"
100000 loops, best of 3: 8.9 usec per loop
(predict)[email protected]:~/src/predict/predict/webapp$ master
$ python -mtimeit "import numpy as np; X = np.ones((100,100));" "X *= np.nan;"
10000 loops, best of 3: 24.9 usec per loop
Как сказано, numpy.empty() - это путь. Однако для объектов fill() может не делать то, что вы думаете:
In[36]: a = numpy.empty(5,dtype=object)
In[37]: a.fill([])
In[38]: a
Out[38]: array([[], [], [], [], []], dtype=object)
In[39]: a[0].append(4)
In[40]: a
Out[40]: array([[4], [4], [4], [4], [4]], dtype=object)
Одним из способов может быть, например:
In[41]: a = numpy.empty(5,dtype=object)
In[42]: a[:]= [ [] for x in range(5)]
In[43]: a[0].append(4)
In[44]: a
Out[44]: array([[4], [], [], [], []], dtype=object)
Другой альтернативой является numpy.broadcast_to(val,n)
, который возвращается в постоянное время независимо от размера, а также наиболее эффективно использует память (он возвращает представление повторяющегося элемента). Предупреждение: возвращаемое значение доступно только для чтения.
Ниже приведено сравнение характеристик всех других методов, которые были предложены с использованием того же теста, что и в ответе Нико Шлёмера.
Еще одна возможность, еще не упомянутая здесь, - использовать NumPy tile:
a = numpy.tile(numpy.nan, (3, 3))
Также дает
array([[ NaN, NaN, NaN],
[ NaN, NaN, NaN],
[ NaN, NaN, NaN]])
Я не знаю о сравнении скорости.