代码之家  ›  专栏  ›  技术社区  ›  Mike T

将数字数组格式设置为类似字符串的数组

  •  0
  • Mike T  · 技术社区  · 7 年前

    我想让Numpy高效地将数字数组(例如float32)的每个元素转换为格式化数组(例如类似字符串)。我可以通过将每个元素迭代到一个列表来实现这一点:

    import numpy as np
    a = (10 ** np.arange(-5, 6, 2, dtype='d') * 3.14159).astype('f')
    # array([3.14159e-05, 3.14159e-03, 3.14159e-01, 3.14159e+01, 3.14159e+03,
    #        3.14159e+05], dtype=float32)
    
    # Good conversion to a list
    print([str(x) for x in a])
    # ['3.14159e-05', '0.00314159', '0.314159', '31.4159', '3141.59', '314159.0']
    print(list(map(lambda x: str(x), a)))  # also does the same
    
    # Expected result: a string-like Numpy array
    print(repr(np.array([str(x) for x in a])))
    # array(['3.14159e-05', '0.00314159', '0.314159', '31.4159', '3141.59',
    #        '314159.0'], dtype='<U11')
    

    然而,这个例子不容易扩展到多维数组,因为 map() 或者列表理解不理解其他维度是如何工作的。我希望将结果作为一个Numpy数组提供,并带有类似字符串的数据类型,如上图所示。


    典型的 numpy.vectorize 可以用来实现这一点,但是我使用Numpy 1.15的每次尝试都不会返回预期结果:

    # Bad conversions with np.vectorize, all show the same result
    f = np.vectorize(lambda x: str(x))
    f = np.vectorize('%s'.__mod__)  # equivalent; gives same result
    f = np.vectorize(lambda x: '{!s}'.format(x))  # also same, but modern formatter
    print(f(a))
    # array(['3.141590059385635e-05', '0.003141589928418398',
    #        '0.31415900588035583', '31.4158992767334', '3141.590087890625',
    #        '314159.0'], dtype='<U21')
    

    (这些结果不好的原因是,Numpy似乎将数据类型从float32升级为Python的原生双精度;类似于 [str(x) for x in a.tolist()] )


    关于如何在任意维Numpy数组上使用map()/list理解和/或修复 np.vectorize 为了达到同样的效果?

    2 回复  |  直到 7 年前
        1
  •  1
  •   ZisIsNotZis    7 年前

    怎么样 np.char.mod ?

    import numpy as np
    np.char.mod('%.2f', np.random.rand(8, 8))
    

    它输出

    array([['0.04', '0.86', '0.74', '0.45', '0.30', '0.09', '0.65', '0.58'],
           ['0.96', '0.58', '0.41', '0.29', '0.26', '0.54', '0.01', '0.59'],
           ['0.38', '0.86', '0.37', '0.14', '0.32', '0.57', '0.19', '0.28'],
           ['0.91', '0.80', '0.78', '0.39', '0.67', '0.51', '0.16', '0.70'],
           ['0.61', '0.12', '0.89', '0.68', '0.01', '0.23', '0.57', '0.18'],
           ['0.71', '0.29', '0.08', '0.01', '0.86', '0.03', '0.79', '0.75'],
           ['0.44', '0.84', '0.89', '0.75', '0.48', '0.88', '0.69', '0.20'],
           ['0.36', '0.69', '0.12', '0.60', '0.16', '0.39', '0.15', '0.02']],
          dtype='<U4')
    
        2
  •  0
  •   Andreas K.    7 年前

    你可以简单地使用 astype 数据类型为“str”

    a.astype(dtype=str)
    
    # array(['3.14159e-05', '0.00314159', '0.314159', '31.4159', '3141.59',
    #       '314159.0'], dtype='<U32')
    

    编辑:刚刚看到你的评论,你已经自己弄明白了。不过,我会保留我的答案。