【问题标题】:Numpy converting array from float to stringsNumpy 将数组从浮点数转换为字符串
【发布时间】:2011-07-18 22:36:00
【问题描述】:

我有一个浮点数组,我已经标准化为一个(即数组中的最大数字是 1),我想将它用作图形的颜色索引。在使用 matplotlib 使用灰度时,这需要使用 0 到 1 之间的字符串,所以我想将浮点数组转换为字符串数组。我试图通过使用“astype('str')”来做到这一点,但这似乎会创建一些与原始值不同(甚至接近)的值。

我注意到这一点是因为 matplotlib 抱怨在数组中找到数字 8,这很奇怪,因为它被归一化为 1!

简而言之,我有一个 float64 的数组 phi,这样:

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

不为空。这令人费解,因为(希望天真地)它似乎是 numpy 中的一个错误,有什么我可能做错了导致这种情况吗?

编辑:经过调查,这似乎是由于字符串函数处理高精度浮点数的方式。使用向量化的 toString 函数(来自 robbles 的答案),情况也是如此,但是如果 lambda 函数是:

lambda x: "%.2f" % x

然后绘图工作 - 越来越好奇。 (显然数组不再相等!)

【问题讨论】:

    标签: python numpy matplotlib


    【解决方案1】:

    您似乎对 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 字符串数组。这通常是个坏主意,从您对问题的描述中,我没有理由首先使用它们...

    【讨论】:

    • 使用 numpy 字符串数组的原因是因为 matplotlib 需要正确形状的字符串迭代,这些字符串表示 0 到 1 之间的数字以表示灰度(当时我想要)。将我必须的数字数组转换为字符串数组似乎最简单。我没有预料到长度的复杂性。
    • 在这种情况下也很有帮助:1.) 从文件中读取数据 2.) 假设所有条目都是 float,但是,有些是 nan。 3.) 如果全部读取为浮点数,列表中会有double64 变量显示为nan 但不被识别为numpy.nan 4.) 为了替换这些,我成功使用了:@ 987654337@
    • 您可以使用 np.genfromtxt 并自动(或多或少地)处理这个问题。如果您打算将它们用作浮点数,那么将浮点数转换为字符串总是一个坏主意。
    • 我知道这已经有 7 年的历史了,但我发表评论是因为情况不再如此(python 3.6;np 1.14.0)
    【解决方案2】:

    如果你有一个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)
    

    【讨论】:

    • 这不是问题所在。你正在创建一个list,他想要一个 numpy 数组。
    • 如果不清楚,我很抱歉,但我正在处理 numpy 数组,而不是 python 列表。更重要的是,我的数组是二维的,所以 1dim 列表理解不起作用。我完全知道我可以创建一个中间 python 列表,然后转换为一个 numpy 数组,但似乎上面的这种方法应该有效,并且使用中间列表是额外(慢)编程。
    • 如果一个对象可以被迭代(比如一个列表或一个 numpy 数组),它支持列表推导。它不需要是一个列表(鸭子打字)
    • 是的,但是你没有得到一个 numpy 数组,是吗?
    • Arrieta:它不起作用,因为当使用多维数组时,列表推导将迭代 numpy.ndarrays,而不是单个数字
    【解决方案3】:

    这可能比你想要的慢,但你可以这样做:

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

    当它从 float64 转换为 str 时,它看起来会四舍五入,但这样您就可以随心所欲地自定义转换。

    【讨论】:

    • 这也不起作用,这导致我建议将非常小的数字转换为字符串失败? IE。该数组包含顺序为 10^-30 的数字。
    • 你的意思是你得到不同的结果?我刚才用一个小的 2D 数组尝试了它,它工作了 - 也许这是一个错误......
    • 好的,现在我看到了同样的情况,但数字非常小。也许这是一个一般的浮点数学问题?
    • 我确实得到了不同的结果,但也许限制不是由于数字的数量级而是由于精确度?(虽然用科学记数法描述)。编辑:如果这是一个浮点问题,什么样的浮点错误会将一个远小于 1 的数字误认为是 8 左右的一个?哈哈
    【解决方案4】:

    如果主要问题是从浮点数转换为字符串时精度损失,一种可能的方法是将浮点数转换为decimalS:http://docs.python.org/library/decimal.html

    在 python 2.7 及更高版本中,您可以直接将浮点数转换为 decimal 对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-28
      • 1970-01-01
      • 2013-03-22
      • 1970-01-01
      • 2019-10-31
      • 1970-01-01
      • 1970-01-01
      • 2011-11-25
      相关资源
      最近更新 更多