2014-07-11 301 views
5

我正在將一個numpy稀疏數組(densed)保存到csv中。結果是我有一個3GB的CSV。問題是95%的單元格是0.0000。我用fmt='%5.4f'。我如何格式化和保存,以便將零保存爲0,非零浮點以'%5.4f'格式保存?如果我能做到這一點,我相信我可以將3GB降至300MB。如何在numpy savetxt中格式化,使得零僅保存爲「0」

我使用

np.savetxt('foo.csv', arrayDense, fmt='%5.4f', delimiter = ',') 

感謝 問候

+0

使用不同的非密集存儲格式可能會產生更好的結果。有關如何執行此操作,請參閱http://stackoverflow.com/questions/8955448/save-load-scipy-sparse-csr-matrix-in-portable-data-format。 – user2357112

+0

另外,考慮壓縮它。如果文件名以'.gz'結尾,'savetxt'和'loadtxt'自動使用gzip;這可能是縮小文件的一種簡單方法。 – user2357112

回答

6

如果您查看np.savetxt的源代碼,您會發現雖然有相當多的代碼來處理Python 2和Python 3之間的參數和差異,但它最終只是一個簡單的python循環遍歷行,其中每行都被格式化並寫入文件。所以如果你自己寫的話,你不會失去任何表現。例如,這裏有一個相比下來函數寫入緊湊零:

def savetxt_compact(fname, x, fmt="%.6g", delimiter=','): 
    with open(fname, 'w') as fh: 
     for row in x: 
      line = delimiter.join("0" if value == 0 else fmt % value for value in row) 
      fh.write(line + '\n') 

例如:

In [70]: x 
Out[70]: 
array([[ 0.  , 0.  , 0.  , 0.  , 1.2345 ], 
     [ 0.  , 9.87654321, 0.  , 0.  , 0.  ], 
     [ 0.  , 3.14159265, 0.  , 0.  , 0.  ], 
     [ 0.  , 0.  , 0.  , 0.  , 0.  ], 
     [ 0.  , 0.  , 0.  , 0.  , 0.  ], 
     [ 0.  , 0.  , 0.  , 0.  , 0.  ]]) 

In [71]: savetxt_compact('foo.csv', x, fmt='%.4f') 

In [72]: !cat foo.csv 
0,0,0,0,1.2345 
0,9.8765,0,0,0 
0,3.1416,0,0,0 
0,0,0,0,0 
0,0,0,0,0 
0,0,0,0,0 

然後,只要你寫你自己的savetxt功能,你還不如讓它處理稀疏矩陣,因此在保存之前不必將其轉換爲(密集)numpy數組。 (我假設稀疏數組是使用來自scipy.sparse的稀疏表示之一實現的。)在以下函數中,唯一的更改是從... for value in row... for value in row.A[0]

​​

例子:

In [112]: a 
Out[112]: 
<6x5 sparse matrix of type '<type 'numpy.float64'>' 
    with 3 stored elements in Compressed Sparse Row format> 

In [113]: a.A 
Out[113]: 
array([[ 0.  , 0.  , 0.  , 0.  , 1.2345 ], 
     [ 0.  , 9.87654321, 0.  , 0.  , 0.  ], 
     [ 0.  , 3.14159265, 0.  , 0.  , 0.  ], 
     [ 0.  , 0.  , 0.  , 0.  , 0.  ], 
     [ 0.  , 0.  , 0.  , 0.  , 0.  ], 
     [ 0.  , 0.  , 0.  , 0.  , 0.  ]]) 

In [114]: savetxt_sparse_compact('foo.csv', a, fmt='%.4f') 

In [115]: !cat foo.csv 
0,0,0,0,1.2345 
0,9.8765,0,0,0 
0,3.1416,0,0,0 
0,0,0,0,0 
0,0,0,0,0 
0,0,0,0,0 
+0

非常感謝沃倫。這一定會奏效。我的稀疏矩陣是TfidfVectorizer模型轉換的結果。它返回一個float64雙尺寸稀疏數組像下面(比方說我正在考慮10個頂部術語)\ N'(0,9)\t 0.434529124115 (0,8)\t 0.506103404485 (0,6)\t 0.342163203439 (0,5 )\t 0.114195114018 (0,4)\t 0.228240906166 (0,0)\t 0.506863556372 (1,9)\t 0.179650406184 (1,8)\t 0.650974675792 (1,5)\t 0.385568606136 (1,3)\t (1,2)\t 0.117613972075 (1,1)\t 0.34801600856 (1,0)\t 0.27164684163 ...'。順便說一句,0.4克fmt本身也有效。 – Run2

2

這將是好得多,如果你在你的稀疏矩陣(m在下面的例子中)只保存非零項,你可以實現這樣做:

fname = 'row_col_data.txt' 
m = m.tocoo() 
a = np.vstack((m.row, m.col, m.data)).T 
header = '{0}, {1}'.format(*m.shape) 
np.savetxt(fname, a, header=header, fmt=('%d', '%d', '%5.4f')) 

和稀疏矩陣可以重新構圖做:

row, col, data = np.loadtxt(fname, skiprows=1, unpack=True) 
shape = map(int, open(fname).next()[1:].split(',')) 
m = coo_matrix((data, (row, col)), shape=shape) 
+0

嗨卡斯特羅 - 感謝您的答覆。我從中學到了很多東西。但是,事情是我需要csv(n,m)行列格式和所有m列。這是因爲我需要將它加載到WEKA和SMOTE中。您的方法是以(n1,2)行的列格式創建xls,並且也缺少0值。 – Run2

+0

CT Zhu已經正確回答 - 但由於某種原因該帖子被刪除。我不能選擇它作爲正確的答案。只有在保存時才使用'fmt ='%。4g''解決了它。如果CT Zhu在幾天內不再添加該帖子,我會添加一個答案。 – Run2

+0

@ Run2'0'的值不會丟失,這是因爲它們沒有存儲在一個稀疏矩陣中,這就是使用這種矩陣的主要目的,所以我相信你不必擔心'0'值...如果你需要一個密集的數組,你可以使用'm.toarray()',在那裏你可以看到零...... –

4

那可能工作給你的要求是 'G' 說明另一種簡單的選擇。如果你關心的是有效位數,而不是關於精確的x位數,並且不介意它在科學和浮點數之間切換,那麼這個技巧很好。例如:

np.savetxt("foo.csv", arrayDense, fmt='%5.4g', delimiter=',') 

如果arrayDense是這樣的:

matrix([[ -5.54900000e-01, 0.00000000e+00, 0.00000000e+00], 
    [ 0.00000000e+00, 3.43560000e-08, 0.00000000e+00], 
    [ 0.00000000e+00, 0.00000000e+00, 3.43422000e+01]]) 

你的方式會產生:

-0.5549,0.0000,0.0000 
0.0000,0.0000,0.0000 
0.0000,0.0000,34.3422 

以上會產生相反:

-0.5549, 0, 0 
0,3.436e-08, 0 
0, 0,34.34 

這種方式是也更加靈活。請注意,使用'g'而不是'f',您不會丟失數據(即3.4356e-08而不是0.0000)。這顯然取決於你設置精度的內容。