2016-08-03 22 views
5

Üç değer içeren bu listelerin her biri ile birlikte 300.000 liste üzerinde çalışacak olan yuvalanmış bir döngüyü vectorize etmeyi arıyorum. Yuvalanmış döngü, listelerin her birinin değerlerini diğer listelerdeki karşılık gelen değerlerle karşılaştırır ve yalnızca aralarında 0.1 arasında bir maksimum farka sahip karşılık gelen değerlere sahip liste dizinlerini ekler. Bu nedenle, [0.234, 0.456, 0.567] ve [0.246, 0.479, 0.580] içeren bir liste, bu kategoriye girer, çünkü karşılık gelen değerleri (0.234 ve 0.246; 0.456 ve 0.479; 0.567 ve 0.580), farklıdır. aralarında 0.1'den az.İç içe geçmiş bir döngüyü vektörle eşleştirme

Şu anda bunu yapmak için aşağıdaki yuvalanmış döngüyü kullanıyorum, ancak şu an tamamlanması yaklaşık 58 saat sürecektir (toplam 90 trilyon yineleme);

import numpy as np 
variable = np.random.random((300000,3)).tolist() 
out1=list() 
out2=list() 
for i in range(0:300000): 
    for j in range(0:300000): 
     if ((i<j) and ((abs(variable[i][0]-variable[j][0]))<0.1) and ((abs(variable[i][1]-variable[j] [1]))<0.1) and ((abs(variable[i][2]-variable[j][2]))<0.1)): 
     out1.append(i) 
     out2.append(j) 
+0

Sizin 'variable', rastgele sadece örneğin, ya da sen aslında taklit edilir bir şey? – Julien

+0

Evet, sadece örnek için - gerçekte, bahsettiğim eşiğe ait veriye sahip olan bir simülasyon yoluyla oluşturulan bir liste listem var. – JBorg

cevap

3

Scipy.spatial'e bakın; Bu tür mekansal sorguları verimli bir şekilde çözmek için birçok işleve sahiptir; Özellikle KDTrees, yani:

import scipy.spatial 
out = scipy.spatial.cKDTree(variable).query_pairs(r=0.1, p=np.infinity) 
+0

Bunu denedi; "Şamandıra gerekli" oluyor. Bunun basit bir şey olduğunu düşünüyorum. cevabın için teşekkürler! – JBorg

+0

Ah Dokümanları yanlış anladım; Bu konuda özellikle açık değiller. Düzenlemeyi dene. 'Sonsuzluk-normu' aradığınız metriğe doğru kaymalıdır; bileşenlerden herhangi birinin maksimum mutlak değeri. –

+0

, verimlilik açısından, listelerin tamamen ndarraylar lehine sonuçlanması gerektiğini belirtmektedir. Bu sizin girişiniz için de geçerli; Bu aramaya output_type = 'ndarray' kwarg ekleyebileceğinizi unutmayın. –

3

Daha sonra NumPy işlevlerini daha kolay kullanabilmek için NumPy dizisine dönüştürün. Daha sonra iki yaklaşım önerilebilir.

Yaklaşım 1.

NumPy yayın 3D diziler bu genişletmek ve vektörleşen şekilde işlemleri gerçekleştirmek için de kullanılabilir. Böylece, şöyle bir uygulama olurdu -

th = 0.1 # Threshold 
arr = np.asarray(variable) 
out1,out2 = np.where(np.triu((np.abs(arr[:,None,:] - arr) < th).all(-1),1)) 

Yaklaşım # 2

böyle tekrarlamalar sorumlu olacak seçici indeksleri kullanan bellek verimliliği üzerinde odaklanarak

Alternatif uygulama -

th = 0.1 # Threshold 
arr = np.asarray(variable) 
R,C = np.triu_indices(arr.shape[0],1) 
mask = (np.abs(arr[R] - arr[C])<th).all(-1) 
out1,out2 = R[mask], C[mask] 
+0

Eğer bir terabayt ram olsaydı, bu işe yarardı, evet :) –

+0

@EelcoHoogendoorn 'Yaklaşım # 2' daha az ağır olabilir :) – Divakar

+0

bunu denedi, ama bellek hatası alıp-kaçırdı; sadece 30.000 liste ile tekrar denedi ve hala çalışıyor; Sanırım hala uzun sürecek mi? 256Gb RAM üzerinde çalışıyor – JBorg

İlgili konular