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

时间:2015-12-18 06:35:22

标签: python arrays string numpy delimiter

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

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

到一个字符串,其中列条目由一个分隔符分隔' \ t'并且这些行由另一个分隔符分隔' \ 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=''
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:

方法1:

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

方法2:

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

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

跟进问题

谢谢Mike,

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

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

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

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

    方法2

    <html>
    
    <head>
    
      <body>
        <div class="display_wait_overlay">
          <div class="section wrapper">
            <div id="test-not" class="fade modal text-left">
              <div id="monthlyinvoiceremainder" class="fade modal text-left">
                <div id="monthlyinvoiceremainderBox" class="btm_bx">
                  <div id="depositDetailsResponse" class="fade modal text-left">
                    <div id="depositDetails" class="fade modal text-left">
                      <footer class="footer navbar_custom" style="">
                        <div class="datepicker datepicker-dropdown dropdown-menu datepicker-orient-left datepicker-orient-bottom" style="display: block; top: 155.933px; left: 758.133px;">
                          <div class="datepicker-days" style="display: none;">
                            <div class="datepicker-months" style="display: none;">
                              <div class="datepicker-years" style="display: block;">
                                <table class="table-condensed">
                                  <thead>
                                    <tr>
                                      <th class="prev" style="visibility: visible;">«</th>
                                      <th class="datepicker-switch" colspan="5">2010-2019</th>
                                      <th class="next" style="visibility: hidden;">»</th>
                                    </tr>
                                  </thead>
                                  <tbody>
                                    <tr>
                                      <td colspan="7">
                                        <span class="year old">2009</span>
                                        <span class="year">2010</span>
                                        <span class="year">2011</span>
                                        <span class="year">2012</span>
                                        <span class="year">2013</span>
                                        <span class="year">2014</span>
                                        <span class="year">2015</span>
                                        <span class="year disabled">2016</span>
                                        <span class="year disabled">2017</span>
                                        <span class="year disabled">2018</span>
                                        <span class="year disabled">2019</span>
                                        <span class="year new disabled">2020</span>
                                      </td>
                                    </tr>
                                  </tbody>
                                  <tfoot>
                                </table>
                              </div>
                            </div>
      </body>
    
    </html>

    有更好的方法吗?

2 个答案:

答案 0 :(得分: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()相比可以使+=更快。

答案 1 :(得分:0)

使用Python3,我只用了一行:

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

输出(固定宽度):

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