2016-12-01 50 views
0

我試圖執行this answer中給出的解決方案,將我的〜3.3GB ASCII讀取爲ndarray指定不同的dtypes,同時使用np.fromiter讀取大型ASCII作爲numpy數組

def iter_loadtxt(filename, delimiter=None, skiprows=0, dtype=float): 
    def iter_func(): 
     with open(filename, 'r') as infile: 
      for _ in range(skiprows): 
       next(infile) 
      for line in infile: 
       line = line.rstrip().split(delimiter) 
       for item in line: 
        yield dtype(item) 
     iter_loadtxt.rowlength = len(line) 

    data = np.fromiter(iter_func(), dtype=[('',np.float),('',np.float),('',np.float),('',np.int),('',np.int),('',np.int),('',np.int)]) 
    data = data.reshape((-1, iter_loadtxt.rowlength)) 
    return data 

data = iter_loadtxt(fname,skiprows=1) 

現在我想輸入不同dtypes在調用np.fromiter,希望,如果我的大多數列是:

事實上,當使用這個功能對我的文件,我得到一個MemoryError整數,而不是浮動我會有足夠的運氣來避免內存問題,但我迄今沒有成功。

我的文件是「多行」X 7列,我想指定以下格式:前三列爲float,以下爲uint。我的操作系統是Windows 10 64位,我有8GB的RAM。我正在使用Python 2.7 32位。

我的嘗試是(以下this answer):

data = np.fromiter(iter_func(), dtype=[('',np.float),('',np.float),('',np.float),('',np.int),('',np.int),('',np.int),('',np.int)]) 

,但我收到TypeError: expected a readable buffer object

EDIT1

由於hpaulj誰提供的解決方案。以下是工作代碼。

def iter_loadtxt(filename, delimiter=None, skiprows=0, dtype=float): 
    def iter_func(): 
     dtypes = [float, float, float, int, int, int, int] 
     with open(filename, 'r') as infile: 
      for _ in range(skiprows): 
       next(infile) 
      for line in infile: 
       line = line.rstrip().split(delimiter) 
       values = [t(v) for t, v in zip(dtypes, line)] 
       yield tuple(values) 
     iter_loadtxt.rowlength = len(line) 

    data = np.fromiter(iter_func(), dtype=[('',np.float),('',np.float),('',np.float),('',np.int),('',np.int),('',np.int),('',np.int)]) 

    return data 

data = iter_loadtxt(fname,skiprows=1) 
+1

你的第一個步驟應該是停止使用32位Python和使用64位的Python來代替。這將解鎖機器上的其餘內存。 –

+0

你在一個小文件上測試了這個嗎? 'iter_func'產生一個浮點數據流,不需要按行分組。我懷疑'from_iter'是否可以處理複合dtype。 – hpaulj

+0

@JohnZwinck確實。 Python的64位版本讓我處理整個文件。謝謝。 – umbe1987

回答

1

對於足夠大的輸入文件,任何代碼(無論簡化如何)都會遇到內存錯誤。

與所有漂浮的7列陣列將佔用56個字節;與混合dtype 40.不完全是一個大的變化。如果它之前通過文件的1/3存在內存錯誤,它現在會觸及它(理論上1/2是通過的)。

iter_func讀取文件,和飼料彩車源源不斷(它自己的D型)。它不返回按行分組的浮動。它保留了一些行數,在最後使用它來重塑1d數組。

fromiter可以處理複合D型,但只有當你給它適當大小的元組。

In [342]: np.fromiter([(1,2),(3,4),(5,6)],dtype=np.dtype('i,i')) 
Out[342]: 
array([(1, 2), (3, 4), (5, 6)], 
     dtype=[('f0', '<i4'), ('f1', '<i4')]) 

In [343]: np.fromiter([1,2,3,4],dtype=np.dtype('i,i')) 
--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
<ipython-input-343-d0fc5f822886> in <module>() 
----> 1 np.fromiter([1,2,3,4],dtype=np.dtype('i,i')) 

TypeError: a bytes-like object is required, not 'int' 

更改iter_func到這樣的事情可能工作(未測試):

def iter_func(): 
    dtypes=[float,float,float,int,int,int,int] 
    with open(filename, 'r') as infile: 
     for _ in range(skiprows): 
      next(infile) 
     for line in infile: 
      line = line.rstrip().split(delimiter) 
      values = [t(v) for t,v in zip(dtypes, line)] 
      yield tuple(values) 
arr = np.fromiter(iter_func, dtype=[('',np.float),('',np.float),('',np.float),('',np.int),('',np.int),('',np.int),('',np.int)]) 
+0

謝謝,我會試試這個。然而,我安裝了一個64位版本的python,並且經歷了這個過程的最後階段(儘管時間很長!)。根據你之前的回答(我在自己的問題中提到),我認爲這將是一個很好的降低計算時間的方法。當我確認這種情況,並確認您的新代碼有效時,我會很樂意接受您的答案。 – umbe1987

+0

我應該在'arr = np.fromiter(iter_func,dtype = ...)'中使用'dtype'參數?我不太明白這一點......對不起,但是從[函數頁面](https://docs.scipy.org/doc/numpy/reference/generated/numpy.fromiter.html),這不是明確。 – umbe1987

+0

我在'iter_func'中定義了'dtypes'列表來匹配你在你的問題中嘗試過的'dtype'參數 - 一個混合了浮點數和整數的參數。 – hpaulj