2011-03-19 517 views
18

我有一個浮點數組,我已歸一化(即數組中的最大數爲1),我想將它用作圖的顏色索引。在使用matplotlib來使用灰度時,這需要使用0到1之間的字符串,所以我想將浮點數組轉換爲一個字符串數組。我試圖通過使用「astype('str')」來做到這一點,但是這似乎創建了一些與原件不一樣(甚至接近)的值。numpy將數組從浮點數轉換爲字符串

我注意到這一點,因爲matplotlib抱怨發現數組中的數字8,這是奇怪的,因爲它被標準化爲一個!

總之,我有一個數組PHIS的float64,使得:

numpy.where(phis.astype('str').astype('float64') != phis) 

是非空的。這很令人困惑,因爲(希望天真地)它似乎是一個在numpy中的錯誤,是否有什麼我可以做錯誤的導致這個?

編輯:調查後,這似乎是由於字符串函數處理高精度浮線的方式。使用矢量化功能的toString(從robbles回答),這也是如此,但是如果lambda函數是:

lambda x: "%.2f" % x 

然後繪圖工作 - 奇妙而又奇妙。 (顯然,陣列不再平等,但!)

回答

29

你似乎有點困惑,numpy的陣列幕後是如何工作的。陣列中的每個項目必須是相同的尺寸

浮點數的字符串表示不會以這種方式工作。例如,repr(1.3)產生'1.3',但repr(1.33)產生'1.3300000000000001'

浮點數的精確字符串表示形式產生可變長度字符串。

由於numpy的陣列由該都具有相同的大小的元素,numpy的需要時,你正在使用字符串數組,以指定該陣列中的字符串的長度。

如果使用x.astype('str'),它總是會轉化東西長度爲1

例如字符串數組,使用x = np.array(1.344566)x.astype('str')產量'1'

您需要更多地說明並使用'|Sx' dtype語法,其中x是數組中每個元素的字符串長度。

例如,使用x.astype('|S10')到陣列轉換爲長度10

甚至更​​好的字符串,只是避免使用字符串numpy的陣列完全。它通常是一個壞主意,並沒有任何理由,我可以從你的問題擺在首位使用它們的說明,請參見...

+0

使用numpy數組的字符串的原因是因爲matplotlib需要一個正確形狀的可迭代字符串,它表示0到1之間的數字以表示灰度(在我想要的時候)。將我需要的數字數組轉換成字符串數組似乎是最簡單的。我沒有預料到這個長度的複雜性。 – VolatileStorm 2011-03-23 10:13:33

+0

在這種情況下也很有用:1.)從文件2中讀取數據。)假設所有條目都是'float',但是有些是'nan'。 3.)如果所有的都讀爲float,那麼在列表中會出現'double64'變量,它們顯示爲'nan',但不會被識別爲'numpy.nan')4.爲了替換這些,我成功地使用了:'if V [-1] .astype('| S3')=='nan':V [-1] = numpy.nan' – Schorsch 2014-03-21 15:25:15

+0

你可以使用np.genfromtxt並自動處理這個(或多或少)。如果你打算將它們用作浮點數,將浮點數轉換爲字符串總是一個壞主意。 – Vincenzooo 2016-05-16 17:10:36

12

如果你有numbers數組,你想要的strings一個數組,你可以這樣寫:

strings = ["%.2f" % number for number in numbers] 

如果您的號碼是花車,該數組與具有兩位小數的字符串相同的數字。

>>> a = [1,2,3,4,5] 
>>> min_a, max_a = min(a), max(a) 
>>> a_normalized = [float(x-min_a)/(max_a-min_a) for x in a] 
>>> a_normalized 
[0.0, 0.25, 0.5, 0.75, 1.0] 
>>> a_strings = ["%.2f" % x for x in a_normalized] 
>>> a_strings 
['0.00', '0.25', '0.50', '0.75', '1.00'] 

注意,它也可以與numpy陣列:

>>> a = numpy.array([0.0, 0.25, 0.75, 1.0]) 
>>> print ["%.2f" % x for x in a] 
['0.00', '0.25', '0.50', '0.75', '1.00'] 

如果你有一個多維陣列類似的方法,可以使用:

new_array = numpy.array(["%.2f" % x for x in old_array.reshape(old_array.size)]) 
new_array = new_array.reshape(old_array.shape) 

實施例:

>>> x = numpy.array([[0,0.1,0.2],[0.3,0.4,0.5],[0.6, 0.7, 0.8]]) 
>>> y = numpy.array(["%.2f" % w for w in x.reshape(x.size)]) 
>>> y = y.reshape(x.shape) 
>>> print y 
[['0.00' '0.10' '0.20'] 
['0.30' '0.40' '0.50'] 
['0.60' '0.70' '0.80']] 

如果您檢查Matplotlib example for the function you are using,您會注意到它們使用了類似的方法:構建空矩陣並使用插值方法構建的字符串填充它。引用的代碼的相關部分是:

colortuple = ('y', 'b') 
colors = np.empty(X.shape, dtype=str) 
for y in range(ylen): 
    for x in range(xlen): 
     colors[x, y] = colortuple[(x + y) % len(colortuple)] 

surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, facecolors=colors, 
     linewidth=0, antialiased=False) 
+0

這不是問題。你正在創建一個'list',他想要一個numpy數組。 – 2011-03-19 23:18:10

+0

我很抱歉,如果它不清楚,但我正在處理numpy數組,而不是python列表。更重要的是,我的數組是2維的,所以1dim列表理解不起作用。我完全知道我可以創建一箇中間python列表,然後轉換爲一個numpy數組,但是它似乎像上面的這個方法應該工作,並且它是額外的(慢)編程來使用中間列表。 – VolatileStorm 2011-03-19 23:19:18

+0

如果一個對象可以迭代(如列表或numpy數組),它支持列表理解。它不需要成爲一個列表(鴨子打字) – Escualo 2011-03-19 23:25:38

1

,這大概比你想要的速度較慢,但​​你可以這樣做:

>>> tostring = vectorize(lambda x: str(x)) 
>>> numpy.where(tostring(phis).astype('float64') != phis) 
(array([], dtype=int64),) 

看起來它捨去值時,將其轉換爲str從float64,但這種方式,你可以自定義轉換,但你喜歡。

+0

這也不管用,這使我認爲非常小的數字爲字符串的轉換,失敗?即該數組包含數量爲10^-30的數字。 – VolatileStorm 2011-03-19 23:36:05

+0

你的意思是你得到不同的結果?我現在試着用一個小的2D陣列,它工作 - 也許這是一個錯誤... – robbles 2011-03-19 23:38:19

+0

好吧,現在我看到相同的事情,真的很小的數字。也許這是一個普遍的浮點數學問題? – robbles 2011-03-19 23:44:55

1

如果主要問題是從浮點數轉換爲字符串時精度的損失,一種可行的方法是將浮點數轉換爲decimal S:http://docs.python.org/library/decimal.html

在python 2中。7和更高版本,您可以直接將浮點數轉換爲decimal對象。