2009-11-10 14 views
101

I mają następujące oznaczenia:Inicjowanie numpy matrycy na inną niż zero lub jeden

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

Tworzy szerokość x wysokość x 9 matrycy wypełnione zerami. Zamiast tego chciałbym się dowiedzieć, czy istnieje funkcja lub sposób inicjowania ich zamiast NaN.

Czy są jakieś? Bez konieczności uciekania się do ręcznego robienia pętli i takich?

Dzięki

+2

Jednym z zastrzeżeń jest to, że NumPy nie ma liczby całkowitej NA (w przeciwieństwie do R). Zobacz [panda lista gotchas] (http://pandas.pydata.org/pandas-docs/stable/gotchas.html). W związku z tym 'np.nan' idzie nie tak po konwersji na int. – smci

+0

smci ma rację. Dla NumPy nie ma takiej wartości NaN. Zależy więc od typu i NumPy, która wartość będzie dla NaN. Jeśli nie jesteś tego świadomy, spowoduje to kłopoty. – Ralf

Odpowiedz

152

Rzadko potrzeba pętli do operacji wektorowych w numpy. Można utworzyć niezainicjowanej tablicę i przypisać do wszystkich wpisów na raz:

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

mam czasowe alternatywy a[:] = numpy.nan tutaj i a.fill(numpy.nan) jak wysłane przez Blaenk:

$ 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 

Te czasy pokazują preferencja dla ndarray.fill(..) jako szybsza alternatywa. OTOH, lubię wygodną implementację numpy, w której można przypisywać wartości do całych plasterków w tym czasie, intencje kodu są bardzo jasne.

+2

Zgadzam się, że zamiar twojego kodu jest wyraźniejszy. Ale dziękuję za nieokreślone czasy (a raczej fakt, że nadal je wysłałeś), doceniam to :) –

+2

Podoba mi się ten: 'a = numpy.empty ((3, 3,)) * numpy.nan'. Czas ten był szybszy niż "wypełnij", ale wolniej niż metoda przypisania, ale jest on onlinerem !! – heltonbiker

+2

Proszę spojrzeć na tę odpowiedź: http://stackoverflow.com/questions/10871220/making-a-matrix-square-and-padding-it-with-desired-value-in-numpy – Ivan

23

Czy znasz numpy.nan?

Można tworzyć własne metody, takie jak:

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

Następnie

nans([3,4]) 

byłoby wyjście

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

znalazłem ten kod w mailing list thread.

+1

Wygląda na przesadę. –

83

Inną opcją jest użycie numpy.full, opcję dostępną w NumPy 1.8+

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

To jest dość elastyczny i można wypełnić go z żadnym innym numerem, który chcesz.

+1

jest to mniej więcej tak szybko, jak przyjęta odpowiedź. – dbliss

+8

Uznalbym to za * najbardziej poprawną * odpowiedź, ponieważ jest to dokładnie to, do czego służy "pełne". 'np.empy ((x, y)) * np.nan' jest dobrym runner-upem (i kompatybilnością ze starszymi wersjami numpy). – travc

+0

to jest wolniej, że 'zapisz' '' 'python -mtimeit" importuje numpy jako np; a = np.empty ((100,100)); " "a.fill (np.nan)" 100000 pętli, najlepiej z 3: 13,3 usec na pętlę python -mtimeit "import numpy jako np; a = np.full ((100,100), np.nan);" 100000 pętli, najlepiej 3: 18,5 usec na pętlę '' ' – Farnabaz

10

zawsze można użyć mnożenie jeśli nie od razu przypomnieć .empty lub .full metody:

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

Oczywiście to działa w żadnej innej wartości liczbowej, a także:

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

Ale @ u0b34a0f6ae's accepted answer jest 3x szybszy (cykle procesora, a nie cykle mózgowe, aby zapamiętać zdumiewającą składnię;):

$ 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)[email protected]:~/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

Tak jak powiedziałeś, numpy.empty() jest drogą do zrobienia.Jednak dla obiektów, wypełnić() nie może zrobić dokładnie to, co myślisz, że to robi:

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) 

Jednym ze sposobów obejścia może być np:

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) 
+0

Poza tym, że nie ma praktycznie nic wspólnego z pierwotnym pytaniem, schludne. –

+0

Cóż, chodzi o "Inicjowanie numpy matrix na czymś innym niż zero lub jeden", w przypadku "coś innego" jest obiektem :) (Bardziej praktycznie, Google doprowadziło mnie tutaj do inicjalizacji z pustą listą) – ntg

15

Porównałem sugerowanych alternatyw dla prędkości i stwierdził, dla wystarczająco dużych wektorów/macierzy do wypełnienia, wszystkie alternatywy z wyjątkiem val * ones i array(n * [val]) są równie szybkie.

enter image description here


Kod odtworzyć działki:

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)' 
    ) 
0

Jeszcze inna możliwość jeszcze nie wspomniano tutaj jest użycie NumPy płytki:

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

daje również

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

Nie wiem o porównaniu prędkości.

Powiązane problemy