Tworzy width x height x 9macierz wypełnioną zerami. Zamiast tego chciałbym wiedzieć, czy istnieje funkcja lub sposób na ich zainicjowanie zamiast NaNs w łatwy sposób.
Jednym zastrzeżeniem jest to, że NumPy nie ma wartości całkowitej NA (w przeciwieństwie do R). Zobacz listę pand gotch . Stąd np.nanźle idzie po konwersji na int.
smci
smci ma rację. Dla NumPy nie ma takiej wartości NaN. Zależy więc od typu i od NumPy, która wartość będzie dla NaN. Jeśli nie jesteś tego świadomy, spowoduje to kłopoty
MasterControlProgram
Odpowiedzi:
271
Rzadko potrzebujesz pętli do operacji wektorowych w Numpy. Możesz utworzyć niezainicjowaną tablicę i przypisać do wszystkich wpisów jednocześnie:
>>> a = numpy.empty((3,3,))>>> a[:]= numpy.nan
>>> a
array([[NaN,NaN,NaN],[NaN,NaN,NaN],[NaN,NaN,NaN]])
Sprawdziłem alternatywne opcje a[:] = numpy.nantutaj i a.fill(numpy.nan)opublikowane przez Blaenka:
$ 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
Czasy pokazują preferencje dla ndarray.fill(..) jako najszybszą alternatywę. OTOH, podoba mi się implementacja wygody numpy, w której możesz przypisywać wartości do całych wycinków w tym czasie, intencja kodu jest bardzo jasna.
Pamiętaj, że ndarray.fillwykonuje swoją operację w miejscu, więc numpy.empty((3,3,)).fill(numpy.nan)wróci None.
Wolę tę .fill()metodę, ale różnica prędkości zmniejsza się praktycznie do zera, ponieważ tablice stają się większe.
naught101
4
... ponieważ np.empty([2, 5])tworzy tablicę, a następnie fill()modyfikuje tablicę w miejscu, ale nie zwraca kopii ani referencji. Jeśli chcesz wywoływać np.empty(2, 5)według nazwy („przypisać do zmiennej”), musisz to zrobić przed wykonaniem na nim operacji w miejscu. To samo dzieje się, jeśli to zrobisz [1, 2, 3].insert(1, 4). Lista jest tworzona, a 4 wstawiane, ale nie można uzyskać odniesienia do listy (i dlatego można założyć, że została ona wyrzucona). W przypadku niezmiennych danych, takich jak ciągi, zwracana jest kopia, ponieważ nie można operować w miejscu. Pandy mogą robić obie rzeczy.
flutefreak7
164
Inną opcją jest użycie numpy.fullopcji dostępnej w NumPy 1.8+
a = np.full([height, width,9], np.nan)
Jest to dość elastyczne i możesz wypełnić go dowolną inną liczbą.
Uznałbym to za najbardziej poprawną odpowiedź, ponieważ jest to właściwie to, co fulljest przeznaczone. np.empy((x,y))*np.nanjest dobrym drugim miejscem (i kompatybilnością ze starszymi wersjami numpy).
travc
jest to wolniejsze niżfillpython -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 Jeśli umieścisz równoważny kod wewnątrz pętli czasowej, będą one mniej więcej takie same. Dwie metody są w zasadzie równe, po prostu masz „np.empty” poza licznikiem czasu w pierwszej. 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 Staniewiczowa
48
Porównałem sugerowane alternatywy prędkości i stwierdziłem, że dla wystarczająco dużych wektorów / macierzy do wypełnienia wszystkie alternatywy oprócz val * onesi array(n * [val])są równie szybkie.
Kod do odtworzenia fabuły:
import numpy
import perfplot
val =42.0def 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)",)
@MadPhysicist To zależy całkowicie od twojej sytuacji. Jeśli musisz zainicjować tylko jedną pojedynczą tablicę NaN, to tak, funkcja niestandardowa prawdopodobnie przesadza. Jeśli jednak musisz zainicjować tablicę NaN w kilkudziesięciu miejscach w kodzie, posiadanie tej funkcji stanie się całkiem wygodne.
Xukrao
1
@Xukaro. Nie bardzo, biorąc pod uwagę, że istnieje już bardziej elastyczna i wydajna wersja takiej funkcji, o której wspominano w wielu innych odpowiedziach.
Mad Physicist
10
Zawsze możesz użyć mnożenia, jeśli nie przywołujesz natychmiast metod .emptylub .full:
Ale zaakceptowana odpowiedź @ u0b34a0f6ae jest 3 razy szybsza (cykle procesora, a nie cykle mózgowe do zapamiętania składni numpy;):
$ 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
Inną alternatywą jest numpy.broadcast_to(val,n) która powraca w stałym czasie niezależnie od wielkości i jest również najbardziej wydajna pod względem pamięci (zwraca widok powtarzanego elementu). Zastrzeżenie polega na tym, że zwrócona wartość jest tylko do odczytu.
Poniżej znajduje się porównanie wyników wszystkich innych metod, które zostały zaproponowane przy użyciu tego samego testu porównawczego, co w odpowiedzi Nico Schlömera .
Jak powiedziano, numpy.empty () jest właściwą drogą. Jednak w przypadku obiektów funkcja fill () może nie działać dokładnie tak, jak myślisz:
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 sposobem 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)
Poza tym, że praktycznie nie ma nic wspólnego z pierwotnym pytaniem, schludnie.
Szalony fizyk
1
Cóż, chodzi o „Inicjowanie macierzy numpy na coś innego niż zero lub jeden”, w przypadku, gdy „coś innego” jest obiektem :) (Praktycznie, Google zaprowadził mnie tutaj do inicjowania z pustą listą)
NT
3
Jeszcze inną możliwością, o której jeszcze nie wspomniano, jest użycie płytki NumPy:
np.nan
źle idzie po konwersji na int.Odpowiedzi:
Rzadko potrzebujesz pętli do operacji wektorowych w Numpy. Możesz utworzyć niezainicjowaną tablicę i przypisać do wszystkich wpisów jednocześnie:
Sprawdziłem alternatywne opcje
a[:] = numpy.nan
tutaj ia.fill(numpy.nan)
opublikowane przez Blaenka:Czasy pokazują preferencje dla
ndarray.fill(..)
jako najszybszą alternatywę. OTOH, podoba mi się implementacja wygody numpy, w której możesz przypisywać wartości do całych wycinków w tym czasie, intencja kodu jest bardzo jasna.Pamiętaj, że
ndarray.fill
wykonuje swoją operację w miejscu, więcnumpy.empty((3,3,)).fill(numpy.nan)
wróciNone
.źródło
a = numpy.empty((3, 3,)) * numpy.nan
.fill
Mierzył czas szybciej niż, ale wolniej niż metoda przypisania, ale jest oneliner !!.fill()
metodę, ale różnica prędkości zmniejsza się praktycznie do zera, ponieważ tablice stają się większe.np.empty([2, 5])
tworzy tablicę, a następniefill()
modyfikuje tablicę w miejscu, ale nie zwraca kopii ani referencji. Jeśli chcesz wywoływaćnp.empty(2, 5)
według nazwy („przypisać do zmiennej”), musisz to zrobić przed wykonaniem na nim operacji w miejscu. To samo dzieje się, jeśli to zrobisz[1, 2, 3].insert(1, 4)
. Lista jest tworzona, a 4 wstawiane, ale nie można uzyskać odniesienia do listy (i dlatego można założyć, że została ona wyrzucona). W przypadku niezmiennych danych, takich jak ciągi, zwracana jest kopia, ponieważ nie można operować w miejscu. Pandy mogą robić obie rzeczy.Inną opcją jest użycie
numpy.full
opcji dostępnej w NumPy 1.8+Jest to dość elastyczne i możesz wypełnić go dowolną inną liczbą.
źródło
full
jest przeznaczone.np.empy((x,y))*np.nan
jest dobrym drugim miejscem (i kompatybilnością ze starszymi wersjami numpy).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
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
Porównałem sugerowane alternatywy prędkości i stwierdziłem, że dla wystarczająco dużych wektorów / macierzy do wypełnienia wszystkie alternatywy oprócz
val * ones
iarray(n * [val])
są równie szybkie.Kod do odtworzenia fabuły:
źródło
numpy.full(n, val)
jest wolniejsze niża = numpy.empty(n) .. a.fill(val)
ponieważ robi to samo wewnętrznieCzy znasz
numpy.nan
?Możesz stworzyć własną metodę, taką jak:
Następnie
wyszedłby
Znalazłem ten kod w wątku listy adresowej .
źródło
Zawsze możesz użyć mnożenia, jeśli nie przywołujesz natychmiast metod
.empty
lub.full
:Oczywiście działa również z dowolną inną wartością liczbową:
Ale zaakceptowana odpowiedź @ u0b34a0f6ae jest 3 razy szybsza (cykle procesora, a nie cykle mózgowe do zapamiętania składni numpy;):
źródło
Inną alternatywą jest
numpy.broadcast_to(val,n)
która powraca w stałym czasie niezależnie od wielkości i jest również najbardziej wydajna pod względem pamięci (zwraca widok powtarzanego elementu). Zastrzeżenie polega na tym, że zwrócona wartość jest tylko do odczytu.Poniżej znajduje się porównanie wyników wszystkich innych metod, które zostały zaproponowane przy użyciu tego samego testu porównawczego, co w odpowiedzi Nico Schlömera .
źródło
Jak powiedziano, numpy.empty () jest właściwą drogą. Jednak w przypadku obiektów funkcja fill () może nie działać dokładnie tak, jak myślisz:
Jednym sposobem może być np .:
źródło
Jeszcze inną możliwością, o której jeszcze nie wspomniano, jest użycie płytki NumPy:
Daje również
Nie wiem o porównaniu prędkości.
źródło