NaN'lerle dolu numpy matrisi oluşturma


195

Takip koduna sahibim:

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

width x height x 9Sıfırlarla dolu bir matris oluşturur . Bunun yerine, NaNkolay bir şekilde s yerine onları başlatmak için bir işlev veya yol olup olmadığını bilmek istiyorum .


2
Bir uyarı, NumPy'nin tamsayı NA değerine sahip olmamasıdır (R'den farklı olarak). Bkz. Pandalar listesi . Bu nedenle np.nanint'ye dönüştürüldüğünde yanlış gidiyor.
smci

smci haklı. NumPy için böyle bir NaN değeri yoktur. Bu nedenle, NaN için türün ve NumPy'nin değerine bağlıdır. Bunun farkında değilseniz, sorunlara neden olacaktır
MasterControlProgram

Yanıtlar:


271

Nadiren numpy vektör işlemleri için döngüler gerekir. Başlatılmamış bir dizi oluşturabilir ve tüm girişlere aynı anda atayabilirsiniz:

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

Alternatifleri a[:] = numpy.nanburada ve a.fill(numpy.nan)Blaenk'in gönderdiği gibi zamanladım :

$ 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

Zamanlamalar ndarray.fill(..)daha hızlı bir alternatif olarak bir tercih göstermektedir . OTOH, numpy'nin o zaman bütün dilimlere değerler atayabileceğiniz kolaylık uygulamasını seviyorum, kodun niyeti çok açık.

Not ndarray.fillyerinde onun işlemini gerçekleştiren, bu yüzden numpy.empty((3,3,)).fill(numpy.nan)onun yerine dönecektir None.


8
Kodunuzun amacının daha açık olduğunu kabul ediyorum. Ama tarafsız zamanlamalar için teşekkürler (ya da daha doğrusu, hala onları yayınladığınız gerçeği), takdir ediyorum :)
Jorge İsrail Peña

2
Bunun gibi I: a = numpy.empty((3, 3,)) * numpy.nan. fillAtama yönteminden daha hızlı ama daha yavaş zamanladı , ancak bir oneliner !!
heltonbiker

2
Lütfen şu cevaba bakın: stackoverflow.com/questions/10871220/…
Ivan

3
.fill()Yöntemi tercih ederim , ancak diziler büyüdükçe hızlardaki fark pratik olarak hiçbir şeye düşmez.
naught101

4
... çünkü np.empty([2, 5])bir dizi oluşturur, ardından fill()o diziyi yerinde değiştirir, ancak bir kopya veya başvuru döndürmez. np.empty(2, 5)Bir ada göre aramak istiyorsanız ("atama değişkendir"), yerinde işlemler yapmadan önce bunu yapmanız gerekir. Yaparsanız aynı tür şeyler olur [1, 2, 3].insert(1, 4). Liste oluşturulur ve 4 eklenir, ancak listeye referans almak imkansızdır (ve bu nedenle çöp toplandığı varsayılabilir). Dizeler gibi değişmez verilerde, yerinde çalışamayacağınız için bir kopya döndürülür. Pandalar her ikisini de yapabilir.
16:16

164

Başka bir seçenek kullanmaktır numpy.full, NumPy 1.8+

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

Bu oldukça esnektir ve istediğiniz başka bir numarayla doldurabilirsiniz.


19
Bunun en doğru cevap olduğunu düşünürüm, çünkü neyin amaçlandığı budur full. np.empy((x,y))*np.naniyi bir ikincilik (ve numpy'nin eski sürümleri için uyumluluk).
travc

bu daha yavaş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 Eğer zamanlama döngüsünün içine eşdeğer bir kod koyarsanız, bunlar neredeyse aynıdır. İki yöntem temelde eşittir, ilkinde zamanlayıcının dışında "np.empty" var. 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

50

Yeterince büyük vektörler / matrisler doldurmak için ben hız için önerilen alternatifler karşılaştırmış ve tespit, tüm hariç alternatifleri val * onesve array(n * [val])eşit hızlı.

resim açıklamasını buraya girin


Grafiği yeniden oluşturmak için kod:

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)",
)

Aynı şeyi dahili olarak yaptığından numpy.full(n, val)daha yavaşa = numpy.empty(n) .. a.fill(val)
endolith

26

Aşina mısın numpy.nan?

Aşağıdaki gibi kendi yönteminizi oluşturabilirsiniz:

def nans(shape, dtype=float):
    a = numpy.empty(shape, dtype)
    a.fill(numpy.nan)
    return a

Sonra

nans([3,4])

çıktı

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

Bu kodu bir posta listesi iş parçacığında buldum .


1
Overkill gibi görünüyor.
Mad Physicist

@MadPhysicist Bu tamamen sizin durumunuza bağlıdır. Yalnızca tek bir NaN dizisini başlatmanız gerekiyorsa, evet, özel bir işlev muhtemelen aşırıdır. Bununla birlikte, kodunuzda düzinelerce yerde bir NaN dizisi başlatmanız gerekiyorsa, bu işleve sahip olmak oldukça uygun hale gelir.
Xukrao

1
@Xukaro. Böyle bir işlevin daha esnek ve verimli bir versiyonunun mevcut olduğu ve diğer birçok cevapta belirtildiği göz önüne alındığında, gerçekte değil.
Mad Physicist

10

.emptyVeya .fullyöntemlerini hemen hatırlamazsanız, çarpma işlemini her zaman kullanabilirsiniz :

>>> np.nan * np.ones(shape=(3,2))
array([[ nan,  nan],
       [ nan,  nan],
       [ nan,  nan]])

Tabii ki başka herhangi bir sayısal değerle de çalışır:

>>> 42 * np.ones(shape=(3,2))
array([[ 42,  42],
       [ 42,  42],
       [ 42, 42]])

Ancak @ u0b34a0f6ae'nin kabul edilen cevabı 3 kat daha hızlıdır (CPU döngüleri, numpy sözdizimini hatırlamak için beyin döngüleri değil;):

$ 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

Başka bir alternatif numpy.broadcast_to(val,n) boyuttan bağımsız olarak sabit sürede dönen ve aynı zamanda en fazla bellek verimli olanıdır (tekrarlanan elemanın bir görünümünü döndürür). Uyarı, döndürülen değerin salt okunur olmasıdır.

Aşağıda, Nico Schlömer'in cevabı ile aynı kriter kullanılarak önerilen diğer tüm yöntemlerin performanslarının bir karşılaştırması verilmiştir .

resim açıklamasını buraya girin


5

Söylendiği gibi, numpy.empty () yoludur. Ancak nesneler için, fill () işlevi tam olarak ne düşündüğünü yapamayabilir:

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)

Bunun bir yolu örneğin:

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)

Orijinal soru ile neredeyse hiçbir ilgisi olmasının yanı sıra, temiz.
Mad Physicist

1
Eh, "Numpy matrisi sıfır veya bir dışında bir şeye başlatma", "başka bir şey" bir nesne ise :) (Daha pratik olarak, google beni boş bir listeyle başlatmak için buraya
getirdi

3

Burada henüz bahsedilmeyen bir başka olasılık da NumPy döşemesini kullanmaktır:

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

Ayrıca verir

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

Hız karşılaştırmasını bilmiyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.