将2d numpy数组转换为字符串

问题描述 投票:4回答:2

我是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))

然后我通过2种方法之一产生b:

方法1:

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

方法2:

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的两个维度上的迭代器,但是,Python如何“知道”它们,以及它们应该在哪个维度上进行迭代?例如,在Matlab中,必须明确说明这些内容。
  3. 是否可以独立设置每列的精度(例如,我希望前三列为%0.3f,最后一列为%0.0f)?
  4. 是否有一种简单的方法可以执行相反的过程-即给定b,生成a?我想出了两种方法:

方法1

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

方法2

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

还有更好的方法吗?

python arrays string numpy delimiter
2个回答
4
投票

解决方案

单线将做:

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()的速度比+=快得多。


0
投票

使用Python3,我只用了一行:

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

输出(固定宽度):

'191.25    0.      0.      1.      191.251   0.      0.      1.      191.252   0.      0.      1.     '
© www.soinside.com 2019 - 2024. All rights reserved.