Инициализация пустой матрицы для чего-то отличного от нуля или единицы - PullRequest
147 голосов
/ 10 ноября 2009

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

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

Создает матрицу шириной x высотой x 9, заполненную нулями. Вместо этого я хотел бы знать, есть ли функция или способ инициализировать их вместо NaN.

Есть ли? Не прибегая к ручному выполнению циклов и тому подобному?

Спасибо

Ответы [ 8 ]

216 голосов
/ 10 ноября 2009

Вам редко нужны циклы для векторных операций в 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, когда вы можете назначать значения целым слайсам в то время, намерение кода очень ясно.

120 голосов
/ 10 октября 2014

Другим вариантом является использование numpy.full, опция доступна в NumPy 1.8 +

a = np.full([height, width, 9], np.nan)

Это довольно гибко, и вы можете заполнить его любым другим номером.

34 голосов
/ 10 июля 2017

Я сравнил предложенные альтернативы по скорости и обнаружил, что для заполнения достаточно больших векторов / матриц все альтернативы, кроме 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)'
    )
25 голосов
/ 10 ноября 2009

Вы знакомы с 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]])

Я нашел этот код в ветке списка рассылки .

10 голосов
/ 31 декабря 2014

Вы всегда можете использовать умножение, если не сразу вспоминаете методы .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 раза быстрее (циклы ЦП, а не циклы мозга для запоминания синтаксиса;)

$ 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
4 голосов
/ 27 мая 2015

Как уже говорилось, 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)

Может быть наоборот, например ::1004

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)
2 голосов
/ 24 декабря 2017

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

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

Также дает

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

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

1 голос
/ 29 ноября 2018

Другой альтернативой является numpy.broadcast_to(val,n), который возвращается в постоянное время независимо от размера, а также наиболее эффективно использует память (он возвращает представление повторяющегося элемента). Предупреждение: возвращаемое значение доступно только для чтения.

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

enter image description here

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