2016-04-07 32 views
0

Bir matristeki en sık öğe öğesini komşu değerlerine ve kendisine göre hesaplamalıyım. Ne istediğimi hesaplamak için kullandığım bir generic_filter işlev buldum. Yani burada ben bir 2d dizisi3d dizilim üzerinde ndimage.generic_function

arr = np.array([ 
    [1, 2, 4], 
    [5, 6, 7], 
    [2, 4, 4] 
]) 

def most_frequent(arr): 
    def most_frequent(val): 
     return Counter(val).most_common(1)[0][0] 

    footprint = [[1, 1, 1], [1, 1, 1], [1, 1, 1]] 
    return ndimage.generic_filter(arr, most_frequent, footprint=footprint, mode='constant') 

print most_frequent(arr) 

için yapabilir nasıl Bu kenarında unsurları görmezden bana

[[0 0 0] 
[0 4 0] 
[0 0 0]] 

döndürür. Gördüğünüz gibi orta element 4'tür çünkü bu komşular ve değer arasında en sık görülen bir unsurdur.


Büyük sorun, 3d matris için aynı şeyi yapmam gerektiğidir. Bu

arr = np.array([ 
    [[1, 1], [2, 2], [4, 4]], 
    [[5, 5], [6, 6], [7, 7]], 
    [[2, 2], [4, 4], [4, 4]] 
]) 

gibi bir matris için Yani ortada yerde ve [4, 4][0, 0] almak için bekliyoruz. Bu, RuntimeError('filter footprint array has incorrect shape.') ile başarısız olur.

cval: Ben dokümanlar söylemek için burada generic_filter kullanabilirsiniz şüphelerim var kötü şey modu ‘sabit’ ise skaler, isteğe bağlı değer girişinin geçmiş kenarlarını doldurmak için.

Sorunumu nasıl çözebilirim?

+0

3B giriş dizisi sadece tamsayılar içeriyor mu? – Divakar

+0

Bir soru daha - Bu süzgeci, tüm yön boyunca e 3D dizi herhangi bir uzunlukta olabilir ve sadece '' (3,3,2) 'değil, değil mi? – Divakar

cevap

1

İşte tam olarak çözümlenmiş bir çözüm.

İlk yapmak düzleştirilmiş mahalleler:

(n,m,_)=M.shape 
(sn,sm,s2)=M.strides 
newshape=(n-2,m-2,9,2) 
newstrides=(sn,sm,2*s2,s2) 
neighborhoods=np.lib.stride_tricks.as_strided(M,newshape,newstrides) 
""" 
array([[[[1, 1], 
     [2, 2], 
     [4, 1], 
     [1, 1], 
     [5, 5], 
     [6, 6], 
     [7, 7], 
     [2, 3], 
     [2, 2]], 

     [[2, 2], 
     [4, 1], 
     [1, 1], 
     [5, 5], 
     [6, 6], 
     [7, 7], 
     [2, 3], 
     [2, 2], 
     [4, 1]]]]) 
    """ 

Sonra 1D dizilerle çalışmak np.unique kullanmak iki bileşeni paketi gerekiyor.

def mostfreq(arr): 
    _,index,counts=unique(arr, return_index=True, return_counts=True) 
    return index[counts.argmax()] 

:

packed_neighborhoods=np.ascontiguousarray(neighborhoods).view(int64) 
In [5]: packed_neighborhoods.shape 
Out[5]: (1, 2, 9, 1) 

Şimdi np.unique dayalı bir 1D dizi çekmek ve en sık indisi bulmak bir işlev, tanımlayın: varsayarak M.dtype int32, sen görünümü tarafından bunu yapabilir

ind2=apply_along_axis(mostfreq,2,packed_neighborhoods).squeeze() 

Ve diğer endekslere dahil sonuç vardır: iyi ekseni üzerinde uygulayın.

ind0,ind1=indices(neighborhoods.shape[:2]) 
print(neighborhoods[ind0,ind1,ind2]) 
""" 
[[[1 1] 
    [4 1]]] 
""" 

Ama çözüm şu anda aynı performansa sahiptir;. Bunu başarmak için nasıl bulduk (

+0

Vay, işe yaramış gibi görünüyor. Araştırmak için biraz zaman alacağım.Bu şekilde bir ayak izi değiştirme fikrini nasıl buldunuz? –

+0

'Filtre ayak izi dizisi yanlış şekildedir.' . veri ndim'e uyacak bir boyut eklemelisiniz. Düzenlenen. –

+0

Orada bir sorun var gibi görünüyor. Örneğin bu dizi için arr = 'np.array ([ [[1, 1], [2, 2], [4, 1], [1, 1]], [[5, 5], [6 6], [7, 7], [2, 3]], [[2, 2], [4, 1], [4, 4], [2, 3]] ]) 'biri sonuçlar '[2 1]' dır ancak bu eleman dizide mevcut değildir. –

0

bir yolu daha iyi bir çözüm arayan

def most_frequent(M): 
    x, y, _ = arr.shape 
    res = np.zeros((x - 2, y - 2, 2)) 
    for i in xrange(1, x - 1): 
     for j in xrange(1, y - 1): 
      neighbors = [M[i - 1, j - 1], M[i - 1, j], M[i - 1, j + 1], M[i, j - 1], M[i, j], M[i, j + 1], M[i + 1, j - 1], M[i + 1, j], M[i + 1, j + 1]] 
      res[i - 1, j - 1] = Counter([tuple(_) for _ in neighbors]).most_common(1)[0][0] 

    return res 
Hala

gibi bir şey yaparak olduğunu (benim 2 döngülerimi içermeyen)

+0

'M' giriş 3B dizisi ile aynı mı? – Divakar

+0

@Divakar evet, öyle –