NumPy dizi başlatma (aynı değerlerle doldur)


237

nHer eleman olan uzunluk bir NumPy dizi oluşturmak gerekiyor v.

Şundan daha iyi bir şey var mı:

a = empty(n)
for i in range(n):
    a[i] = v

Biliyorum zerosve onesv = 0, ben kullanabilir 1. işine yarayacak v * ones(n)ama zaman işi olmaz vise Noneve aynı zamanda çok daha yavaş olacaktır.


1
Bilgisayarımda, 0 durumda, a = np.zeros(n)döngüde kullanmak daha hızlıdır a.fill(0). Bu, a=np.zeros(n)yeni bellek ayırmak ve başlatmak gerektiğini düşündüğüm için beklediğim şeyin tersi. Herkes bunu açıklayabilirse, bunu takdir ediyorum.
user3731622

Hiçbiri bir numpy dizisine koyamazsınız, çünkü Hiçbiri kendi tipine sahipken ve aslında bir işaretçi iken hücreler belirli bir veri türüyle oluşturulur.
Camion

@Camion Evet şimdi biliyorum :) v * ones(n)Pahalı çarpımı kullandığı için elbette hala korkunç. Değiştir *ile +olsa ve v + zeros(n)dışarı dönüşler bazı durumlarda (içinde şaşırtıcı derecede iyi olması için stackoverflow.com/questions/5891410/... ).
maksimum

max, v eklemeden önce sıfırlarla bir dizi oluşturmak yerine, bu diziyi boş olarak oluşturmak var = np.empty(n)ve daha sonra 'var [:] = v' ile doldurmak daha da hızlıdır . (btw, np.full()bu kadar hızlı)
Camion

Yanıtlar:


308

NumPy 1.8 tanıtıldı np.full() den daha doğrudan bir usul olup, empty()bunu takiben fill(), belirli bir değer ile dolu bir dizi oluşturmak için:

>>> np.full((3, 5), 7)
array([[ 7.,  7.,  7.,  7.,  7.],
       [ 7.,  7.,  7.,  7.,  7.],
       [ 7.,  7.,  7.,  7.,  7.]])

>>> np.full((3, 5), 7, dtype=int)
array([[7, 7, 7, 7, 7],
       [7, 7, 7, 7, 7],
       [7, 7, 7, 7, 7]])

Bu tartışmalı olduğu açıkça elde edilen ne tarif eder (ve bu çok özel bir görev sergiler çünkü prensip olarak çok etkili olabilir), çünkü belirli değerler ile dolu bir dizi oluşturma yolu.


1
Bu full () yöntemi benim için iyi çalışıyor, ancak bunun için biraz belge bulamıyorum. Beni doğru yere yönlendiren var mı?
James Adams

1
En azından help(numpy.full)bir Python kabuğunda yapabilirsiniz. Ayrıca web belgelerinde olmadığını şaşırıyorum.
Eric O Lebigot

Sistemimde (Python 2.7, Numpy 1.8), np.full () aslında np.empty () ve ardından np.fill () 'den biraz daha yavaştır.
John Zwinck

1
10.000 element için, aynı şeyi gözlemliyorum (bunun np.fill()olmadığı ve olmaması gerekir arr.fill()), yaklaşık% 10'luk bir farkla. Fark daha büyük olsaydı, NumPy hata izleyicide bir sorun ortaya çıkarırdım. :) Ben zaman yürütme böyle küçük bir fark için, daha açık ve net kod tercih, bu yüzden np.full()her zaman gitmek .
Eric O Lebigot

Makinemde np.full () np.array.fill () ile aynı hızda
Fnord

92

Numpy 1.7.0 için güncellendi: (Hat Bart-@Rolf Bartstra.)

a=np.empty(n); a.fill(5) en hızlı.

Azalan hız sırasına göre:

%timeit a=np.empty(1e4); a.fill(5)
100000 loops, best of 3: 5.85 us per loop

%timeit a=np.empty(1e4); a[:]=5 
100000 loops, best of 3: 7.15 us per loop

%timeit a=np.ones(1e4)*5
10000 loops, best of 3: 22.9 us per loop

%timeit a=np.repeat(5,(1e4))
10000 loops, best of 3: 81.7 us per loop

%timeit a=np.tile(5,[1e4])
10000 loops, best of 3: 82.9 us per loop

13
Daha yeni ve doğrudan için bir zamanlama eklemek np.full()yararlı olacaktır. Makinemde, NumPy 1.8.1 ile, daha az doğrudan fill()sürüme göre yaklaşık% 15 daha yavaş ( full()biraz daha hızlı gitme potansiyeli olduğu gibi beklenmedik ).
Eric O Lebigot

@DavidSanders: Sizi takip ettiğimden emin değilim: fill()en hızlı çözüm. Çarpma çözümü çok daha yavaştır.
Eric O Lebigot

2
Not: hız gerçekten bir endişe ise, 10000bunun yerine bir boyut kullanmak 1e4fark edilir bir fark yaratır, bazı nedenlerden dolayı ( full()neredeyse% 50 daha yavaştır 1e4).
Eric O Lebigot

Sadece sonuçlarımı ekleyerek full(), veri türü açıkça bir kayan nokta olmadığında oldukça yavaş çalışır. Aksi takdirde, buradaki en iyi yöntemlerle karşılaştırılabilir (ancak biraz daha yavaş).
user2699

: @ user2699 100.000 elemanları ile, bu gözlemleyerek değilim full(100000, 5), full(100000, 5, dtype=float), full(100000, 5, dtype=int)ve a =np.empty(100000); a.fill(5)(hiçbir önbelleğe alma: benim makinede aynı anda ilgili tüm take %timeit -r1 -n1 …) (NumPy 1.11.2).
Eric O Lebigot

65

Bunu fillyapmanın en hızlı yolu olduğuna inanıyorum .

a = np.empty(10)
a.fill(7)

Ayrıca her zaman örneğinizde olduğu gibi yinelemekten kaçınmalısınız. Basit bir a[:] = vyöntem, numpy yayın kullanarak yinelemelerinizi gerçekleştirir .


1
Teşekkür ederim. Baktığımda, ihtiyaçlarıma daha iyi uyduğunu fillgördüm repeat.
maksimum

Önerilerinizin a[:]=vgenel olarak toplamdan daha hızlı olduğunu söylemek için cevabınızı güncellemeyi düşünür müsünüz fill?
en fazla

@max Daha hızlı mı? Yayın bir dizi doldurmak için daha genel bir yoldur ve sanırım yavaş veya çok dar kullanım durumunda eşittir fill.
Paul

16

Görünüşe göre, sadece mutlak hızlar değil, aynı zamanda hız sırası (user1579844 tarafından bildirildiği gibi) makineye bağlıdır; bulduğum şey:

a=np.empty(1e4); a.fill(5) en hızlı;

Azalan hız sırasına göre:

timeit a=np.empty(1e4); a.fill(5) 
# 100000 loops, best of 3: 10.2 us per loop
timeit a=np.empty(1e4); a[:]=5
# 100000 loops, best of 3: 16.9 us per loop
timeit a=np.ones(1e4)*5
# 100000 loops, best of 3: 32.2 us per loop
timeit a=np.tile(5,[1e4])
# 10000 loops, best of 3: 90.9 us per loop
timeit a=np.repeat(5,(1e4))
# 10000 loops, best of 3: 98.3 us per loop
timeit a=np.array([5]*int(1e4))
# 1000 loops, best of 3: 1.69 ms per loop (slowest BY FAR!)

Yani, deneyin ve platformunuzda en hızlı olanı kullanın.


14

sahiptim

numpy.array(n * [value])

akılda, ama görünüşe göre bu yeterince büyük için diğer tüm önerilerden daha yavaş n.

İşte perfplot (benim evcil hayvan projem) ile tam karşılaştırma .

resim açıklamasını buraya girin

İki emptyalternatif hala en hızlı olanıdır (NumPy 1.12.1 ile). fullbüyük dizileri yakalar.


Grafiği oluşturmak için kod:

import numpy as np
import perfplot


def empty_fill(n):
    a = np.empty(n)
    a.fill(3.14)
    return a


def empty_colon(n):
    a = np.empty(n)
    a[:] = 3.14
    return a


def ones_times(n):
    return 3.14 * np.ones(n)


def repeat(n):
    return np.repeat(3.14, (n))


def tile(n):
    return np.repeat(3.14, [n])


def full(n):
    return np.full((n), 3.14)


def list_to_array(n):
    return np.array(n * [3.14])


perfplot.show(
    setup=lambda n: n,
    kernels=[empty_fill, empty_colon, ones_times, repeat, tile, full, list_to_array],
    n_range=[2 ** k for k in range(27)],
    xlabel="len(a)",
    logx=True,
    logy=True,
)

7

Şunları kullanabilirsiniz numpy.tile, örneğin:

v = 7
rows = 3
cols = 5
a = numpy.tile(v, (rows,cols))
a
Out[1]: 
array([[7, 7, 7, 7, 7],
       [7, 7, 7, 7, 7],
       [7, 7, 7, 7, 7]])

Her ne kadar tilebir diziyi (bu durumda olduğu gibi bir skaler yerine) 'döşemek' anlamına gelse de, işi her boyutta ve boyutta önceden doldurulmuş diziler oluşturacak şekilde yapar.


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.