Numpy将数组从float转换为字符串

时间:2011-03-19 23:05:12

标签: python numpy matplotlib

我有一个浮点数组,我已经规范化为一个(即数组中最大的数字是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。 (显然,阵列不再相等!)

4 个答案:

答案 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对象。