2011-03-19 513 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对象。