2011-06-16 34 views
9

में पढ़ना यूनिकोड तत्वों नामक एक पाठ फ़ाइल पर विचार करें "new.txt" निम्नलिखित तत्वों से युक्त:numpy सरणी

μm 
∂r 
∆λ 

अजगर 2.7 में, मैं लिखकर फ़ाइल पढ़ सकते हैं:

>>> import codecs 
>>> f = codecs.open('new.txt', encoding='utf-8') 
>>> lines = [line.strip() for line in f2.readlines()] 
>>> lines 
[u'\u03bcm', u'\u2202r', u'\u2206\u03bb'] 
>>> print lines[0] 
μm 

अब तक सब ठीक है। मैं आसानी से के माध्यम से एक numpy सरणी के लिए इस सूची में बदल सकते हैं:

>>> import numpy as np 
>>> arr = np.array(lines) 
>>> arr 
array([u'\u03bcm', u'\u2202r', u'\u2206\u03bb'], 
     dtype='<U2') 

मुद्दा है, मैं इस फ़ाइल सीधे numpy के loadtxt समारोह के माध्यम से नहीं पढ़ सकते हैं:

>>> np.loadtxt('new.txt', dtype=np.unicode_) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib64/python2.7/site-packages/numpy/lib/npyio.py", line 805, in loadtxt 
    X = np.array(X, dtype) 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xce in position 0: ordinal not in range(128) 

पढ़ने के लिए सही तरीका क्या है यह फ़ाइल सीधे numpy में?

धन्यवाद।

उत्तर

8

स्मृति में, यूनिकोड तारों को UCS-2 या UCS-4 के रूप में दर्शाया गया है, इस पर निर्भर करता है कि आपके पायथन दुभाषिया को कैसे संकलित किया गया था। आपकी फ़ाइल UTF-8 में एन्कोड की गई है, इसलिए आपको इसे NumPy सरणी में मैप करने से पहले इसे फिर से रिकोड करने की आवश्यकता है। loadtxt() आपके लिए रिकोडिंग नहीं कर सकता - सभी NumPy मुख्य रूप से संख्यात्मक सरणी पर लक्षित है।

हर पंक्ति मान लिया जाये कि वर्णों की संख्या समान है, आप भी और अधिक कुशल संस्करण

s = codecs.open("new.txt", encoding="utf-8").read() 
arr = numpy.frombuffer(s, dtype="<U3") 

का उपयोग इस तार में नई पंक्ति वर्ण शामिल होंगे सकता है। उन्हें शामिल नहीं करने के लिए, का उपयोग

arr = numpy.frombuffer(s.replace("\n", ""), dtype="<U2") 

संपादित: अपनी फ़ाइल की तर्ज अलग-अलग लंबाई है और आप मध्यवर्ती सूची से बचने के लिए चाहते हैं, तो आप उपयोग कर सकते

arr = numpy.fromiter(codecs.open("new.txt", encoding="utf-8"), dtype="<U2") 

मैं नहीं कर रहा हूँ सुनिश्चित करें कि यह आंतरिक रूप से कुछ अस्थायी सूची बना देगा, हालांकि।

+1

+1 - लेकिन एक नोट: आप सीधे 'loadtxt' पर एक खुली फ़ाइल पास कर सकते हैं, और मेरे लिए,' codecs.open' के साथ फ़ाइल खोलना और इसे 'loadtxt' पर पास करने से समस्या हल हो गई है। या बल्कि एक समान समस्या है, क्योंकि मेरे 'loadtxt' को utf-8 फ़ाइल में कोई समस्या नहीं थी! – senderle

+0

@sendle: अजीब - मेरे लिए काम नहीं करता है। मैं यहाँ NumPy 1.5.1 का उपयोग कर रहा हूँ - शायद यह मायने रखता है। –

+0

क्या इसमें numpy पायथन 3 पोर्ट का उपयोग करने के साथ कुछ भी करना है? मुझे अभी भी मेरी numpy में यूनिकोड एन्कोडर त्रुटि मिलती है जो पायथन 2.7 के तहत काम कर रही है। –

2

आप loadtxt का उपयोग करना चाहते हैं, तो आप या तो पहले लोड कच्चे बाइट सरणी और फिर डिकोड कर सकते हैं:

data = np.loadtxt('foo.txt', dtype='S8') 
unicode_data = data.view(np.chararray).decode('utf-8') 

या डिकोडिंग के लिए एक कनवर्टर निर्दिष्ट करें:

data = np.loadtxt('foo.txt', converters={0: lambda x: unicode(x, 'utf-8')}, dtype='U2') 

लेकिन, जैसा कि fromiter का उपयोग कर स्वेन के जवाब में शायद loadtxt से अधिक प्रभावी होने जा रहा है।