[python] NaN으로 채워진 numpy 행렬 만들기

다음 코드가 있습니다.

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

width x height x 90으로 채워진 행렬을 만듭니다 . 대신, NaN쉬운 방법으로 함수를 초기화하는 기능이나 방법이 있는지 알고 싶습니다 .



답변

numpy에서 벡터 연산을위한 루프가 거의 필요하지 않습니다. 초기화되지 않은 배열을 만들고 한 번에 모든 항목에 할당 할 수 있습니다.

>>> a = numpy.empty((3,3,))
>>> a[:] = numpy.nan
>>> a
array([[ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN]])

Blaenk가 게시 한 대안을 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의 편리한 구현을 사용하여 당시 전체 조각에 값을 할당 할 수 있습니다. 코드의 의도는 매우 분명합니다.

ndarray.fill제자리에서 작업 을 수행하므로 numpy.empty((3,3,)).fill(numpy.nan)대신을 반환 None합니다.


답변

또 다른 옵션은 numpy.fullNumPy 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주기).

$ 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.broadcast_to(val,n)크기에 관계없이 일정한 시간에 반환하고 메모리 효율성이 가장 뛰어납니다 (반복 된 요소의보기를 반환 함). 주의 사항은 반환 값이 읽기 전용이라는 것입니다.

아래는 Nico Schlömer의 답변 과 동일한 벤치 마크를 사용하여 제안 된 다른 모든 방법의 성능을 비교 한 입니다.

여기에 이미지 설명을 입력하십시오


답변

말했듯이, 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)