2012-10-12 16 views
10

Kılavuza karşılık gelen noktaların listesini oluşturmak istiyorum. Yani (0,0) ila (1,1) arasında bir alan ızgarası oluşturmak istersem, puanları (0,0), (0,1), (1,0), (1, 0).Numpy meshgrid noktaları

g = np.meshgrid([0,1],[0,1]) 
np.append(g[0].reshape(-1,1),g[1].reshape(-1,1),axis=1) 

sonucu Verim::

array([[0, 0], 
     [1, 0], 
     [0, 1], 
     [1, 1]]) 

sorum ikilidir:

Bunu aşağıdaki kodla yapılabileceğini biliyoruz

  1. orada daha iyi mi Bunu yapmanın yolu?
  2. Bunu daha yüksek boyutlarda genelleştirmenin bir yolu var mı?

cevap

24

Sadece Numpy içinde belgeler bunu yapmak için daha hızlı bir yol sağlar fark:

X, Y = np.mgrid[xmin:xmax:100j, ymin:ymax:100j] 
positions = np.vstack([X.ravel(), Y.ravel()]) 

Bu kolayca bağlantılı meshgrid2 fonksiyonu kullanılarak ve elde edilen şebekeye 'Ravel' haritalama daha boyutlara genelleştirilmiş edilebilir .

g = meshgrid2(x, y, z) 
positions = np.vstack(map(np.ravel, g)) 

sonuç her bir eksen 1000 kene 3B dizi için fermuar yöntemine göre yaklaşık 35 kat daha hızlıdır.

Kaynak: http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.gaussian_kde.html#scipy.stats.gaussian_kde

iki yöntem aşağıdaki kod bölümleri dikkate karşılaştırmak için:

ızgara oluşturmak için yardımcı olacaktır meşhur kene işaretleri oluşturun.

In [23]: import numpy as np 

In [34]: from numpy import asarray 

In [35]: x = np.random.rand(100,1) 

In [36]: y = np.random.rand(100,1) 

In [37]: z = np.random.rand(100,1) 

meshgrid için bağlantılı mgilson işlevi tanımlayın:

In [38]: def meshgrid2(*arrs): 
    ....:  arrs = tuple(reversed(arrs)) 
    ....:  lens = map(len, arrs) 
    ....:  dim = len(arrs) 
    ....:  sz = 1 
    ....:  for s in lens: 
    ....:  sz *= s 
    ....:  ans = [] 
    ....:  for i, arr in enumerate(arrs): 
    ....:   slc = [1]*dim 
    ....:   slc[i] = lens[i] 
    ....:   arr2 = asarray(arr).reshape(slc) 
    ....:   for j, sz in enumerate(lens): 
    ....:    if j != i: 
    ....:     arr2 = arr2.repeat(sz, axis=j) 
    ....:   ans.append(arr2) 
    ....:  return tuple(ans) 

ızgara ve saati iki işlev oluşturun.

In [39]: g = meshgrid2(x, y, z) 

In [40]: %timeit pos = np.vstack(map(np.ravel, g)).T 
100 loops, best of 3: 7.26 ms per loop 

In [41]: %timeit zip(*(x.flat for x in g)) 
1 loops, best of 3: 264 ms per loop 
+0

Bir hata mesajı var Dosya Dosya "", 1 numaralı hat " \ xxx.py" meshgrid2 slc, hat 816, [i] = mercek [ i] TypeError: 'map' nesnesi subscriptable 'dosyası değil 'xxx.py' işlevini koyduğum yerdir. –

+0

Muhtemelen python3 kullanıyorsunuz, harita bir liste yerine bir yineleyici döndürüyor. Yapılması en kolay şey 'map'' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''''''' (w (map (len, arrs)) '). –

+0

Numune 1.8'in üstünde, meshgrid2' işlevine gerek yoktur, çünkü standart 'meshgrid' daha yüksek boyutları destekler. – fhchl

9

Kılavuz noktalarınız her zaman ayrılmaz mı?

print list(np.ndindex(2,2,2)) 

Maalesef bu karşılanmazsa (0'dan başlayarak) ayrılmaz varsayım beri OP'nin gereksinimlerini karşılamıyor: Eğer öyleyse, numpy.ndindex

print list(np.ndindex(2,2)) 

yüksek boyutlara kullanabilirsiniz . Bu cevabı yalnızca bir başkasının, bu varsayımların doğru olduğu yerde aynı şeyi aradığı durumlarda bırakacağım.


Bunu yapmanın bir başka yolu zip dayanır:

g = np.meshgrid([0,1],[0,1]) 
zip(*(x.flat for x in g)) 

Bu kısım keyfi boyutlara güzel ölçekler. Ne yazık ki, np.meshgrid pek çok boyuta iyi ölçeklenmiyor, bu yüzden parçanın çalışması gerekecek ya da (varsayarak) işe yarayacak, kendi ndmeshgrid işlevinizi oluşturmak için bu SO answer'u kullanabilirsiniz.

+0

İyi öneri, ama ne yazık değiller. Düzenle ... Ayrıca aralıklar mutlaka nokta (0,0, ...) ile başlamaz. –

+0

@juniper - Çok kötü. İlgilenen başka bir çözüm daha ekledim ... – mgilson

+0

Yapacağım. Teşekkürler! 'Traceback (son En son çağrı): –

1

Oysa bunu yapmak için başka bir yoludur: yüksek boyutlara genelleştirilmiş edilebilir

np.indices((2,2)).T.reshape(-1,2) 

, ör .:

In [60]: np.indices((2,2,2)).T.reshape(-1,3) 
Out[60]: 
array([[0, 0, 0], 
     [1, 0, 0], 
     [0, 1, 0], 
     [1, 1, 0], 
     [0, 0, 1], 
     [1, 0, 1], 
     [0, 1, 1], 
     [1, 1, 1]])