【问题标题】:convert 2d numpy array to string将 2d numpy 数组转换为字符串
【发布时间】:2016-03-24 19:36:34
【问题描述】:

我是 Python 新手,正在尝试转换 2d numpy 数组,例如:

a=numpy.array([[191.25,0,0,1],[191.251,0,0,1],[191.252,0,0,1]])

到一个字符串,其中列条目由一个分隔符'\t'分隔,行由另一个分隔符'\n'分隔,并控制每列的​​精度,以获得:

b='191.250\t0.00\t0\t1\n191.251\t0.00\t0\t1\n191.252\t0.00\t0\t1\n'

首先,我通过以下方式创建数组:

import numpy as np

col1=np.arange(191.25,196.275,.001)[:, np.newaxis]
nrows=col1.shape[0]

col2=np.zeros((nrows,1),dtype=np.int)
col3=np.zeros((nrows,1),dtype=np.int)
col4=np.ones((nrows,1),dtype=np.int)

a=np.hstack((col1,col2,col3,col4))

然后我通过以下两种方法之一生成 b:

方法一:

b=''
for i in range(0,a.shape[0]):
    for j in range(0,a.shape[1]-1):
        b+=str(a[i,j])+'\t'
    b+=str(a[i,-1])+'\n'
b

方法二:

b=''
for i in range(0,a.shape[0]):
    b+='\t'.join(['%0.3f' %x for x in a[i,:]])+'\n'
b

但是,我猜有更好的方法来生成 a 和 b。我正在寻找最有效的方法(即内存、时间、代码紧凑性)来创建 a 和 b。


跟进问题

谢谢你,迈克,

b = '\n'.join('\t'.join('%0.3f' %x for x in y) for y in a)+'\n'

为我工作,但我有一些后续问题(评论部分不适合):

  1. 虽然这更紧凑,但速度是否与执行嵌套 for 循环相同,因为这似乎是括号内发生的事情?
  2. 我知道 x 和 y 是跨 y 的 2 个维度的迭代器,但是,Python 如何“知道”它们是什么以及它们应该迭代哪些维度?例如,在 Matlab 中,这些事情必须明确说明。
  3. 有没有办法独立设置每列的精度(例如,我希望前三列使用 %0.3f,最后一列使用 %0.0f)?
  4. 是否有一种简单的方法来执行相反的过程 - 即给定 b,产生 a?我想出了两种方法:

方法一

y=b.split('\n')[:-1]
z=[y[i].split('\t') for i in range(0,len(y))]
a=numpy.array(z,dtype=float)

方法二

import re
a=numpy.array(filter(None,re.split('[\n\t]+',b)),dtype=float).reshape(-1,4)

有没有更好的办法?

【问题讨论】:

    标签: python arrays string numpy delimiter


    【解决方案1】:

    解决方案

    单线就可以了:

    b = '\n'.join('\t'.join('%0.3f' %x for x in y) for y in a)
    

    用一个更简单的例子:

    >>> a = np.arange(25, dtype=float).reshape(5, 5)
    >>> a
    array([[  0.,   1.,   2.,   3.,   4.],
           [  5.,   6.,   7.,   8.,   9.],
           [ 10.,  11.,  12.,  13.,  14.],
           [ 15.,  16.,  17.,  18.,  19.],
           [ 20.,  21.,  22.,  23.,  24.]])
    

    这个:

    b = '\n'.join('\t'.join('%0.3f' %x for x in y) for y in a)
    print(b)
    

    打印这个:

    0.000   1.000   2.000   3.000   4.000
    5.000   6.000   7.000   8.000   9.000
    10.000  11.000  12.000  13.000  14.000
    15.000  16.000  17.000  18.000  19.000
    20.000  21.000  22.000  23.000  24.000
    

    说明

    您已经在第二种方法中使用了列表推导式。这里我们有一个生成器表达式,它看起来与列表推导式完全一样。唯一的语法区别是[]() 替换。 generator expression 不会构建列表,而是将所谓的生成器交给join。最后它具有相同的效果,但跳过了构建这个中间列表的步骤。

    这样的表达式中可以有多个for,这使得它可以嵌套。 这个:

    b = '\n'.join('\t'.join('%0.3f' %x for x in y) for y in a)
    

    相当于:

    res = []
    for y in a:
        res.append('\t'.join('%0.3f' %x for x in y))
    b = '\n'.join(res)
    

    性能

    我在 IPython Notebook 中使用 %%timeit

    %%timeit
    b = '\n'.join('\t'.join('%0.3f' %x for x in y) for y in a)
    
    10 loops, best of 3: 42.4 ms per loop
    
    
    %%timeit
    b=''
    for i in range(0,a.shape[0]):
        for j in range(0,a.shape[1]-1):
            b+=str(a[i,j])+'\t'
        b+=str(a[i,-1])+'\n'
    
    10 loops, best of 3: 50.2 ms per loop
    
    
    %%timeit
    b=''
    for i in range(0,a.shape[0]):
        b+='\t'.join(['%0.3f' %x for x in a[i,:]])+'\n'
    
    10 loops, best of 3: 43.8 ms per loop
    

    看起来它们的速度都差不多。实际上,+= 在 CPython 中进行了优化。否则,它会比join() 方法慢得多。与 += 相比,其他 Python 实现(例如 Jython 或 PyPy)可以显示更大的时间差异,并且可以使 join() 更快。

    【讨论】:

    • 嗨,迈克,谢谢,这对我有用。我有一些后续问题,但无法在此处列出,因此我将它们包含在对原始问题的编辑中。
    • @AB 我为您的前两个附加问题添加了解释。如果它解决了您的问题,您可以accept 一个答案。我想我的答案是。
    • @AB 我建议您创建两个新问题,例如 3. 的“数组行的条件形成”和“如何从字符串制作 NumPy 数组?”为 4. 否则,这个问题变得拥挤。此外,答案也应该对其他人有用。但是你需要一个好的问题表述来找到你正在寻找的东西。在其他问题中隐藏答案无济于事。只需向我指出这些新问题,我就会看看它们。
    【解决方案2】:

    使用 Python3,我只用了一行代码:

    str(a).replace('[','').replace(']','').replace('\n','  ')+'  '
    

    输出(固定宽度):

    '191.25    0.      0.      1.      191.251   0.      0.      1.      191.252   0.      0.      1.     '
    

    【讨论】:

      猜你喜欢
      • 2021-05-27
      • 2013-05-05
      • 2016-03-10
      • 2013-08-14
      • 2021-04-26
      • 2015-03-28
      • 1970-01-01
      • 2013-06-30
      相关资源
      最近更新 更多