2012-08-15 11 views
5

NumPy, 3 bayt ve 6 baytlık türleri için uint24 ve uint48 türlerine yönelik yerleşik desteğe sahip değildir. Bu türleri kullanarak büyük bir veri kümem var ve bunu numpy ile beslemek istiyorum. Şu anda (uint24 için) ne yapıyoruz:NumPy: 3 bayt, 6 baytlık türleri (aka uint24, uint48)

import numpy as np 
dt = np.dtype([('head', '<u2'), ('data', '<u2', (3,))]) 
# I would like to be able to write 
# dt = np.dtype([('head', '<u2'), ('data', '<u3', (2,))]) 
# dt = np.dtype([('head', '<u2'), ('data', '<u6')]) 
a = np.memmap("filename", mode='r', dtype=dt) 
# convert 3 x 2byte data to 2 x 3byte 
# w1 is LSB, w3 is MSB 
w1, w2, w3 = a['data'].swapaxes(0,1) 
a2 = np.ndarray((2,a.size), dtype='u4') 
# 3 LSB 
a2[0] = w2 % 256 
a2[0] <<= 16 
a2[0] += w1 
# 3 MSB 
a2[1] = w3 
a2[1] <<=8 
a2[1] += w2 >> 8 
# now a2 contains "uint24" matrix 

o 100MB girişi için işe yararken, bu (verinin 100s GBs düşünün) verimsiz görünüyor. Daha verimli bir yolu var mı? Örneğin, verilerin bir bölümünü maskeleyen özel bir salt okunur görünüm oluşturmak yararlı olabilir ("iki MSB ile her zaman sıfır" tip "). Sadece verilere salt okunur erişime ihtiyacım var.

cevap

6

Sorduğun şeyi yapmanın bir yolu olduğuna inanmıyorum (bazı mimarilerde oldukça etkisiz olan erişilmemiş erişim gerektirir). Bu her eleman olacak olan Bununla

e = np.ndarray((a.size - 2) // 6, np.dtype('<u8'), buf, strides=(6,)) 

: Sen strides yapıcı parametresini kullanarak unaligned erişim alabilirsiniz

a = np.memmap("filename", mode='r', dtype=np.dtype('>u1')) 
e = np.zeros(a.size/6, np.dtype('>u8')) 
for i in range(3): 
    e.view(dtype='>u2')[i + 1::4] = a.view(dtype='>u2')[i::3] 

: Reading and storing arbitrary byte length integers from a file Benim çözüm bir süreç içi diziye veri aktarımı daha verimli olabilir Bir sonraki ile örtüşüyor, bu yüzden gerçekten kullanmak için erişimdeki yüksek baytları maskelemek zorunda kalacaksınız.

+1

+1. Probs buna değmez. – Joe

+0

Yönteminiz daha güzel görünse de, tüm girdiyi birkaç kez okumaya ve değiştirilmiş bir kopyasını bellekte saklamaya devam eder. Hem sizin hem de orijinal çözümüm 100GB giriş için çalışmaz. –

0

ister büyük ister küçük endian olarak kodlanmış her boyutta tamsayılar okuyabilir aşağıdaki kodu kullanarak:

def readBigEndian(filename, bytesize): 
    with (open(filename,"rb")) as f: 
     str = f.read(bytesize) 
     while len(str)==bytesize: 
      int = 0; 
      for byte in map(ord,str): 
       print byte 
       int = (int << 8) | byte 
      yield(int) 
      str = f.read(bytesize) 

def readLittleEndian(filename, bytesize): 
    with (open(filename,"rb")) as f: 
     str = f.read(bytesize) 
     while len(str)==bytesize: 
      int = 0; 
      shift = 0 
      for byte in map(ord,str): 
       print byte 
       int |= byte << shift 
       shift += 8 
      yield(int) 
      str = f.read(bytesize) 

for i in readLittleEndian("readint.py",3): 
    print i 
1

Orada bu over için bir cevap var: How do I create a Numpy dtype that includes 24 bit integers?

Biraz çirkin, ama tam olarak yapar Ne istediğinizi: <u3 bir dtype var ndarray endekslemenizi sağlar böylece diskten memmap() büyük veri yapabilirsiniz.
Dördüncü örtüşen baytı temizlemek için elle bir bit maskesi uygulamanız gerekir, ancak erişimden sonra dilimlenmiş (çok boyutlu) diziye uygulanabilir.

Hile, bir ndarrayın 'adım' bölümünü kötüye kullanmaktır, böylece dizin oluşturma çalışır. Sınırlar hakkında şikayet etmeden çalışmasını sağlamak için a special trick var. Hizalama sorunları için

İlgili konular