2016-06-04 20 views
7

İlk boyutun bir (R, G, B, A) dörtgösterim anlamına geldiği, sayısal bir sayı dizisi (4, X, Y) var. Amacım, her bir X*Y RGBA dörtlüsünü X*Y kayan nokta değerlerine aktarmak ve bunları eşleştiren bir sözlük vermektir. aşağıdaki gibiEşdüzenli eşleme işleminin performansını artırma

My geçerli kod:

codeTable = { 
    (255, 255, 255, 127): 5.5, 
    (128, 128, 128, 255): 6.5, 
    (0 , 0 , 0 , 0 ): 7.5, 
} 

for i in range(0, rows): 
    for j in range(0, cols): 
     new_data[i,j] = codeTable.get(tuple(data[:,i,j]), -9999) 
data boyutu (4, rows, cols) bir numpy dizi olan

ve new_data boyutu (rows, cols) taşımaktadır.

Kod çalışıyor, ancak oldukça uzun bir zaman alıyor. Bu kod parçasını nasıl optimize etmeliyim? İşte beklenen sonucu döndüren bir yaklaşımdır

import numpy 

codeTable = { 
    (253, 254, 255, 127): 5.5, 
    (128, 129, 130, 255): 6.5, 
    (0 , 0 , 0 , 0 ): 7.5, 
} 

# test data 
rows = 2 
cols = 2 
data = numpy.array([ 
    [[253, 0], [128, 0], [128, 0]], 
    [[254, 0], [129, 144], [129, 0]], 
    [[255, 0], [130, 243], [130, 5]], 
    [[127, 0], [255, 120], [255, 5]], 
]) 

new_data = numpy.zeros((rows,cols), numpy.float32) 

for i in range(0, rows): 
    for j in range(0, cols): 
     new_data[i,j] = codeTable.get(tuple(data[:,i,j]), -9999) 

# expected result for `new_data`: 
# array([[ 5.50000000e+00, 7.50000000e+00], 
#  [ 6.50000000e+00, -9.99900000e+03], 
#  [ 6.50000000e+00, -9.99900000e+03], dtype=float32) 
+0

nasıl verimli ve kısaca sorunu çözmek için kullanılabilecek list.index bir vektörleşen nd-dizi yetenekli varyant içerir çok sayıda 'satır' ve 'cols' var mı? – Will

+0

@Will Her biri için binlerce var. –

+0

Belki bu yardımcı olacaktır: http://stackoverflow.com/questions/36480358/whats-a-fast-non-loop-way-to-apply-a-dict-to-a-ndarray-meaning-use-elements – hpaulj

cevap

1

, ancak bu hızlı sizin için olacaksa verilerinin böyle küçük bir miktarı ile bu bilmek zor: İşte

tam bir örnektir. Ancak, çift döngüden kaçtığım için, oldukça iyi bir hızlanma göreceksiniz.

import numpy 
import pandas as pd 


codeTable = { 
    (253, 254, 255, 127): 5.5, 
    (128, 129, 130, 255): 6.5, 
    (0 , 0 , 0 , 0 ): 7.5, 
} 

# test data 
rows = 3 
cols = 2 
data = numpy.array([ 
    [[253, 0], [128, 0], [128, 0]], 
    [[254, 0], [129, 144], [129, 0]], 
    [[255, 0], [130, 243], [130, 5]], 
    [[127, 0], [255, 120], [255, 5]], 
]) 

new_data = numpy.zeros((rows,cols), numpy.float32) 

for i in range(0, rows): 
    for j in range(0, cols): 
     new_data[i,j] = codeTable.get(tuple(data[:,i,j]), -9999) 

def create_output(data): 
    # Reshape your two data sources to be a bit more sane 
    reshaped_data = data.reshape((4, -1)) 
    df = pd.DataFrame(reshaped_data).T 

    reshaped_codeTable = [] 
    for key in codeTable.keys(): 
     reshaped = list(key) + [codeTable[key]] 
     reshaped_codeTable.append(reshaped) 
    ct = pd.DataFrame(reshaped_codeTable) 

    # Merge on the data, replace missing merges with -9999 
    result = df.merge(ct, how='left') 
    newest_data = result[4].fillna(-9999) 

    # Reshape 
    output = newest_data.reshape(rows, cols) 
    return output 

output = create_output(data) 
print(output) 
# array([[ 5.50000000e+00, 7.50000000e+00], 
#  [ 6.50000000e+00, -9.99900000e+03], 
#  [ 6.50000000e+00, -9.99900000e+03]) 

print(numpy.array_equal(new_data, output)) 
# True 
+0

Çözümünüz sadece kare giriş verileri için çalışıyor gibi görünüyor ve "cols! = Satırlar" olduğunda çalışmaz. Ama fikirler için teşekkürler, ben araştırırım. Her neyse, hız, saf çift döngü çözümümden çok daha tatmin edici. –

+0

Sabit! Bu, istenen sayıda satır ve sütunu alacaktır. –

+0

Eh, kodunuz diğer veri şekilleri için çalışmıyor. İlk mesajımı daha karmaşık bir örnekle güncelledim. Kodunuz doğru sonuçları döndürür, ancak çıkış dizisinde yanlış konumda. –

1

numpy_indexed paketi (uyarı: Ben onun yazarım):

import numpy_indexed as npi 
map_keys = np.array(list(codeTable.keys())) 
map_values = np.array(list(codeTable.values())) 
indices = npi.indices(map_keys, data.reshape(4, -1).T, missing='mask') 
remapped = np.where(indices.mask, -9999, map_values[indices.data]).reshape(data.shape[1:]) 
+0

Çözümünüz çekicilik gibi çalışıyor gibi görünüyor. Teşekkürler! Daha sonra performans iyileştirmeleri hakkında görüşeceğim. –

+0

Performans karşılaştırması için bekliyorum! –