Muszę utworzyć tablicę NumPy o długości n
, której każdy element jest v
.
Czy jest coś lepszego niż:
a = empty(n)
for i in range(n):
a[i] = v
Wiem zeros
i ones
działałbym dla v = 0, 1. Mógłbym użyć v * ones(n)
, ale to nie zadziała, kiedy byłoby znacznie wolniejsze.v
jest None
, a także
a = np.zeros(n)
w pętli jest szybsze niża.fill(0)
. Jest to sprzeczne z oczekiwaniami, ponieważ myślałema=np.zeros(n)
, że będę musiał przydzielić i zainicjować nową pamięć. Jeśli ktokolwiek może to wyjaśnić, byłbym wdzięczny.v * ones(n)
nadal jest okropny, ponieważ używa drogiego mnożenia. Wymień*
się+
jednak, iv + zeros(n)
okazuje się być zaskakująco dobre w niektórych przypadkach ( stackoverflow.com/questions/5891410/... ).var = np.empty(n)
a następnie wypełnić ją „var [:] = v”. (przy okazji,np.full()
jest tak szybki)Odpowiedzi:
Wprowadzono NumPy 1.8
np.full()
, który jest bardziej bezpośrednią metodą niżempty()
następniefill()
tworzenie tablicy wypełnionej pewną wartością:Jest to prawdopodobnie sposób tworzenia tablicę wypełnioną pewnych wartości, ponieważ wyraźnie opisuje, co jest osiągane (i może w zasadzie być bardzo skuteczne, ponieważ wykonuje on bardzo konkretne zadanie).
źródło
help(numpy.full)
w powłoce Pythona. Jestem również zaskoczony, że nie ma go w dokumentacji internetowej.np.fill()
że nie istnieje i powinno byćarr.fill()
), z różnicą około 10%. Gdyby różnica była większa, podniósłbym problem w narzędziu do śledzenia błędów NumPy. :) Wolę bardziej wyraźny i wyraźniejszy kod, z powodu tak niewielkiej różnicy w wykonywaniu czasu, więc idę z tymnp.full()
cały czas.Zaktualizowano dla Numpy 1.7.0: (Porada dla @Rolf Bartstra.)
a=np.empty(n); a.fill(5)
jest najszybszy.W malejącej kolejności prędkości:
źródło
np.full()
Przydatne byłoby dodanie czasu dla najnowszego i bezpośredniego . Na moim komputerze z NumPy 1.8.1 jest on o około 15% wolniejszy niżfill()
wersja mniej bezpośrednia (co jest nieoczekiwane, ponieważfull()
ma potencjał, by iść nieco szybciej).fill()
to najszybsze rozwiązanie. Rozwiązanie do mnożenia jest znacznie wolniejsze.10000
zamiast zamiast1e4
robi zauważalną różnicę z jakiegoś powodu (full()
jest prawie o 50% wolniejsze, z1e4
).full()
działa znacznie wolniej, gdy typ danych nie jest jawnie zmiennoprzecinkowy. W przeciwnym razie jest porównywalny (ale nieco wolniejszy) z najlepszymi tutaj metodami.full(100000, 5)
,full(100000, 5, dtype=float)
,full(100000, 5, dtype=int)
ia =np.empty(100000); a.fill(5)
wszystko bierze o tym samym czasie na moim komputerze (bez buforowania:%timeit -r1 -n1 …
) (NumPy 1.11.2).Uważam, że
fill
to najszybszy sposób na zrobienie tego.Powinieneś także zawsze unikać iteracji, tak jak robisz to w swoim przykładzie. Prosty
a[:] = v
wykona to, co robi twoja iteracja za pomocą nadawania numpy .źródło
fill
, zobaczyłem, żerepeat
jeszcze lepiej odpowiada moim potrzebom.a[:]=v
ogólnie twoja rekomendacja jest szybsza niżfill
?fill
.Najwyraźniej nie tylko prędkości bezwzględne, ale także kolejność prędkości (zgłoszona przez użytkownika 1579844) zależą od maszyny; oto co znalazłem:
a=np.empty(1e4); a.fill(5)
jest najszybszy;W malejącej kolejności prędkości:
Spróbuj więc dowiedzieć się i użyć najszybszego na swojej platformie.
źródło
miałem
na uwadze, ale najwyraźniej jest to wolniejsze niż wszystkie inne propozycje wystarczająco duże
n
.Oto pełne porównanie z perfplot (mój projekt dla zwierząt domowych).
Dwie
empty
alternatywy są nadal najszybsze (z NumPy 1.12.1).full
dogania dużych tablic.Kod do wygenerowania wykresu:
źródło
Możesz użyć
numpy.tile
np .:Chociaż
tile
ma on „kafelkować” tablicę (zamiast skalara, jak w tym przypadku), wykona zadanie, tworząc wstępnie wypełnione tablice o dowolnym rozmiarze i wymiarze.źródło
bez numpy
źródło
[v] * n
byłoby bardziej bezpośrednio związane z pytaniem dotyczącym PO.