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


195

다음 코드가 있습니다.

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

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


2
한 가지주의 사항은 NumPy에 정수 NA 값이 없다는 것입니다 (R과 달리). gotchas의 팬더 목록을 참조하십시오 . 따라서 np.nanint로 변환하면 잘못됩니다.
smci

smci가 옳다. NumPy의 경우 그러한 NaN 값이 없습니다. 따라서 NaN에 대한 값과 NumPy에 따라 다릅니다. 이것을 모른다면 문제가 생길 것입니다
MasterControlProgram

답변:


271

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합니다.


8
귀하의 코드 의도가 더 명확하다는 데 동의합니다. 그러나 편견 타이밍에 대한 감사 (또는 오히려, 사실 당신은 여전히 그들을 게시 됨), 나는 :) 그것을 감사
호르헤 이스라엘 페냐

2
나는 이것을 좋아한다 : a = numpy.empty((3, 3,)) * numpy.nan. 그것은 fill할당 방법보다 빠르지 만 느리게 시간이 걸리지 만 oneliner입니다!
heltonbiker

2
이 답변을보십시오 : stackoverflow.com/questions/10871220/…
Ivan

3
나는 .fill()방법을 선호 하지만 속도의 차이는 배열이 커질수록 거의 아무것도 줄지 않습니다.
naught101

4
... np.empty([2, 5])배열을 만든 다음 fill()해당 배열을 제자리에서 수정하지만 복사본이나 참조를 반환하지 않기 때문입니다. np.empty(2, 5)이름 ( "할당은 변수에 할당") 으로 호출 하려면 적절한 작업을 수행하기 전에 수행해야합니다. 당신도 같은 일이 일어납니다 [1, 2, 3].insert(1, 4). 목록이 작성되고 4가 삽입되었지만 목록에 대한 참조를 얻는 것은 불가능하므로 가비지 수집 된 것으로 가정 할 수 있습니다. 문자열과 같은 변경 불가능한 데이터에서는 제자리에서 작업 할 수 없으므로 복사본이 반환됩니다. 팬더는 둘 다 할 수 있습니다.
flutefreak7 2016 년

164

또 다른 옵션은 numpy.fullNumPy 1.8 이상에서 사용 가능한 옵션 인 을 사용 하는 것입니다

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

이것은 매우 유연하며 원하는 다른 숫자로 채울 수 있습니다.


19
나는 이것이 의도 된 것이므로 이것이 가장 정확한 대답 이라고 생각합니다 full. np.empy((x,y))*np.nan좋은 주자입니다 (그리고 numpy의 이전 버전과의 호환성).
travc

이것은 느리다fill python -mtimeit "import numpy as np; a = np.empty((100,100));" "a.fill(np.nan)" 100000 loops, best of 3: 13.3 usec per loop python -mtimeit "import numpy as np; a = np.full((100,100), np.nan);" 100000 loops, best of 3: 18.5 usec per loop
Farnabaz

5
@Farnabaz 타이밍 루프를 포함하는 동등한 코드를 넣으면 거의 같습니다. 두 가지 방법은 기본적으로 동일합니다. 첫 번째 방법에서 타이머 외부에 "np.empty"가 있습니다. python -mtimeit "import numpy as np; a = np.empty((1000,1000)); a.fill(np.nan)" 1000 loops, best of 3: 381 usec per loop $ python -mtimeit "import numpy as np; a = np.full((1000,1000), np.nan);" 1000 loops, best of 3: 383 usec per loop
Scott Staniewicz

49

나는 제안 된 속도 대안을 비교하고 충분히 큰 벡터 / 행렬을 채울 때를 제외 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.full(n, val)보다 느린 a = numpy.empty(n) .. a.fill(val)내부적 같은 일 않기 때문에
endolith

26

익숙 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]])

메일 링리스트 스레드 에서이 코드를 찾았습니다 .


1
잔인한 것 같습니다.
Mad Physicist

@MadPhysicist 그것은 당신의 상황에 전적으로 달려 있습니다. 하나의 NaN 배열 만 초기화해야하는 경우 사용자 지정 함수가 과도하게 작동 할 수 있습니다. 그러나 코드의 수십 곳에서 NaN 배열을 초기화 해야하는 경우이 기능을 사용하는 것이 매우 편리합니다.
Xukrao

1
@Xukaro. 실제로, 그러한 기능의보다 유연하고 효율적인 버전이 이미 존재하고 여러 다른 답변에서 언급되었다는 것을 감안할 때 실제로는 아닙니다.
Mad Physicist

10

.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

6

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

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

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


5

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

원래 질문과 사실상 아무런 관련이없는 것 외에도 깔끔합니다.
미친 물리학 자

1
글쎄, 그것은 (더 실질적으로, 빈리스트로 초기화 여기 저를지도 구글) : 객체 인 경우에, "다른 무엇인가"를 "0 또는 1 이외의 다른 NumPy와 매트릭스를 초기화"에 관하여
NTG

3

아직 언급되지 않은 또 다른 가능성은 NumPy 타일을 사용하는 것입니다.

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

또한 제공

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

나는 속도 비교에 대해 모른다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.