2012-08-15 17 views
5

NumPy में 3-बाइट और 6-बाइट प्रकार, उर्फ ​​uint24 और uint48 के लिए अंतर्निहित समर्थन की कमी दिखाई देती है। मेरे पास इन प्रकारों का उपयोग करके एक बड़ा डेटा सेट है और इसे खराब करने के लिए फ़ीड करना चाहते हैं। क्या मैं इस समय (uint24 के लिए) कार्य करें:NumPy: 3-बाइट, 6-बाइट प्रकार (उर्फ 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 

हालांकि यह 100 एमबी इनपुट के लिए काम करता है, यह अक्षम लग रहा है (डेटा के 100s GB का के बारे में सोच)। क्या कोई और अधिक प्रभावी तरीका है? उदाहरण के लिए, एक विशेष प्रकार का केवल पढ़ने वाला दृश्य बनाना जो डेटा का मुखौटा हिस्सा उपयोगी होगा ("यूआईएस 64" दो एमएसबी हमेशा शून्य "प्रकार के साथ)। मुझे केवल डेटा तक केवल पढ़ने की आवश्यकता है।

उत्तर

6

मुझे विश्वास नहीं है कि आप जो भी पूछ रहे हैं उसे करने का एक तरीका है (इसे असाइन किए गए एक्सेस की आवश्यकता होगी, जो कुछ आर्किटेक्चर पर अत्यधिक अक्षम है)। Reading and storing arbitrary byte length integers from a file से मेरे समाधान एक में प्रक्रिया सरणी में डेटा स्थानांतरित में और अधिक कुशल हो सकता है:

e = np.ndarray((a.size - 2) // 6, np.dtype('<u8'), buf, strides=(6,)) 
हालांकि इस प्रत्येक तत्व होगा साथ

:

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] 

आप strides निर्माता पैरामीटर का उपयोग कर असंरेखित पहुंच प्राप्त कर सकते हैं अगले के साथ ओवरलैप करें, इसलिए वास्तव में इसका उपयोग करने के लिए आपको पहुंच पर उच्च बाइट्स को मुखौटा करना होगा।

+1

+1। Probs इसके लायक नहीं है। – Joe

+0

आपकी विधि अच्छी तरह दिखती है, फिर भी यह पूरे इनपुट को कई बार पढ़ती है और स्मृति में एक संशोधित प्रति संग्रहित करती है। आपका और मेरा मूल समाधान दोनों 100 जीबी इनपुट के लिए काम नहीं करेगा। –

0

नीचे आप बड़े या छोटे endian के रूप में कोडित किसी भी आकार के पूर्णांक पढ़ सकते हैं कोड का उपयोग करना:

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

वहाँ पर इस से अधिक के लिए एक जवाब है: How do I create a Numpy dtype that includes 24 bit integers?

यह थोड़ा बदसूरत है, लेकिन वास्तव में करता है आप क्या चाहते हैं: आपको अपने ndarray को इंडेक्स करने की अनुमति देता है जैसे कि इसे <u3 का एक प्रकार मिला है ताकि आप डिस्क से memmap() बड़ा डेटा प्राप्त कर सकें।
चौथे ओवरलैपिंग बाइट को साफ़ करने के लिए आपको अभी भी बिटमैस्क मैन्युअल रूप से लागू करने की आवश्यकता है, लेकिन इसे एक्सेस के बाद कटा हुआ (बहुआयामी) सरणी पर लागू किया जा सकता है।

चाल एक अंडायर के 'घुमावदार' हिस्से का दुरुपयोग करना है, ताकि अनुक्रमण कार्य करता है। इसे सीमा के बारे में शिकायत किए बिना इसे काम करने के लिए, a special trick है। संरेखण के मुद्दों के लिए