Mam następujący kod:
r = numpy.zeros(shape = (width, height, 9))
Tworzy width x height x 9
macierz wypełnioną zerami. Zamiast tego chciałbym wiedzieć, czy istnieje funkcja lub sposób na ich zainicjowanie zamiast NaN
s w łatwy sposób.
Mam następujący kod:
r = numpy.zeros(shape = (width, height, 9))
Tworzy width x height x 9
macierz wypełnioną zerami. Zamiast tego chciałbym wiedzieć, czy istnieje funkcja lub sposób na ich zainicjowanie zamiast NaN
s w łatwy sposób.
Odpowiedzi:
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.nan
tutaj 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.fill
wykonuje swoją operację w miejscu, więc numpy.empty((3,3,)).fill(numpy.nan)
wróci None
.
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ę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.
Inną opcją jest użycie numpy.full
opcji 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ą.
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
i array(n * [val])
są równie szybkie.
Kod do odtworzenia fabuły:
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)
jest wolniejsze niż a = numpy.empty(n) .. a.fill(val)
ponieważ robi to samo wewnętrznie
Czy znasz numpy.nan
?
Możesz stworzyć własną metodę, taką jak:
def nans(shape, dtype=float):
a = numpy.empty(shape, dtype)
a.fill(numpy.nan)
return a
Następnie
nans([3,4])
wyszedłby
array([[ NaN, NaN, NaN, NaN],
[ NaN, NaN, NaN, NaN],
[ NaN, NaN, NaN, NaN]])
Znalazłem ten kod w wątku listy adresowej .
Zawsze możesz użyć mnożenia, jeśli nie przywołujesz natychmiast metod .empty
lub .full
:
>>> np.nan * np.ones(shape=(3,2))
array([[ nan, nan],
[ nan, nan],
[ nan, nan]])
Oczywiście działa również z dowolną inną wartością liczbową:
>>> 42 * np.ones(shape=(3,2))
array([[ 42, 42],
[ 42, 42],
[ 42, 42]])
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)
Jeszcze inną możliwością, o której jeszcze nie wspomniano, jest użycie płytki NumPy:
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.
np.nan
źle idzie po konwersji na int.