我有一个浮点数组,我已经规范化为一个(即数组中最大的数字是1),我想用它作为图形的颜色索引。在使用matplotlib来使用灰度时,这需要使用0到1之间的字符串,所以我想将浮点数组转换为字符串数组。我试图通过使用“astype('str')”来做到这一点,但这似乎创造了一些与原件不同(甚至接近)的值。
我注意到这一点,因为matplotlib抱怨在数组中找到数字8,这很奇怪,因为它被标准化为1!
简而言之,我有一个float64的数组phis,这样:
numpy.where(phis.astype('str').astype('float64') != phis)
非空。这是令人费解的(希望天真)它似乎是一个numpy的错误,有什么我可能做错了导致这个?
编辑:调查后,这似乎是由于字符串函数处理高精度浮点数的方式。使用vectorized toString函数(从robbles回答),情况也是如此,但是如果lambda函数是:
lambda x: "%.2f" % x
然后图形工作 - curiouser和curiouser。 (显然,阵列不再相等!)
答案 0 :(得分:31)
你似乎对numpy数组如何在幕后工作感到困惑。数组中的每个项目必须是相同大小。
float的字符串表示形式不起作用。例如,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字符串数组。这通常是一个坏主意,我没有理由从你对你的问题的描述中看到它们首先使用它们......
答案 1 :(得分:13)
如果你有一个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)
答案 2 :(得分:1)
这可能比你想要的要慢,但你可以这样做:
>>> tostring = vectorize(lambda x: str(x))
>>> numpy.where(tostring(phis).astype('float64') != phis)
(array([], dtype=int64),)
当它从float64转换为str时,它似乎会将值四舍五入,但这样您就可以根据需要自定义转换。
答案 3 :(得分:1)
如果主要问题是从浮点数转换为字符串时精度损失,一种可能的方法是将浮点数转换为decimal
S:http://docs.python.org/library/decimal.html。
在python 2.7及更高版本中,您可以直接将float转换为decimal
对象。