Инициализация матрицы numpy значением, отличным от нуля или единицы

StackOverflow https://stackoverflow.com/questions/1704823

  •  19-09-2019
  •  | 
  •  

Вопрос

У меня есть следующий код:

r = numpy.zeros(shape = (width, height, 9))

Он создает матрицу ширины x высоты 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) как написал Бленк:

$ 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]) одинаково быстры.

enter image description here


Код для воспроизведения сюжета:

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 раза быстрее (циклы процессора, а не циклы мозга для запоминания синтаксиса 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)laneh@predict:~/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) который возвращается в постоянное время независимо от размера, а также является наиболее эффективным с точки зрения использования памяти (он возвращает представление повторяющегося элемента).Предостережение заключается в том, что возвращаемое значение доступно только для чтения.

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

enter image description here

Еще одна возможность, еще не упомянутая здесь, — это использование плитки NumPy:

a = numpy.tile(numpy.nan, (3, 3))

Также дает

array([[ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN]])

Я не знаю, как сравнивать скорости.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top