【问题标题】:numpy save an array of different types to a text filenumpy 将不同类型的数组保存到文本文件中
【发布时间】:2013-04-08 14:31:08
【问题描述】:

假设我有以下 numpy 结构化数组:

>>> a = numpy.array((1, 2.0, 'buckle_my_shoe'),dtype=('i4,f8,a14')) 
array((1, 2.0, 'buckle_my_shoe'), 
  dtype=[('f0', '<i4'), ('f1', '<f8'), ('f2', 'S14')])

我想将其保存到文本文件中的单个空格或制表符分隔的行中。如果数组都是同一类型,我可以使用numpy.savetxt('myfile.dat,myarray,newline=" ")。但是,这似乎不像混合数据类型/结构化数组,例如:

file('myfile.dat', 'a')
numpy.savetxt('myfile.dat',a,newline=" ")

给出这个错误:

IndexError: tuple index out of range

谁能推荐一个这样做的方法?

【问题讨论】:

    标签: python file-io numpy newline


    【解决方案1】:

    编辑:无论出于何种原因,我似乎都无法独自回答这个问题,所以这里有一个更简洁的版本,它不必要地使用 csv 模块。郑重声明,@askewchan 的回答还是更好!

    a = numpy.array([(1, 2.0, 'buckle_my_shoe'),
                     (3,4.0,'lock_the_door')],dtype=('i4,f8,a14'))
    with open('test.txt','w') as f:
         f.write(' '.join([str(item) for sublist in a for item in sublist]))
    print open('test.txt','r').read()
    

    输出:

    1 2.0 buckle_my_shoe 3 4.0 lock_the_door
    

    【讨论】:

      【解决方案2】:

      如果你有一个像你的例子一样的零维数组,那么你可以这样做:

      b = np.array((1, 2.0, 'buckle_my_shoe'), 
               dtype=[('f0', '<i4'), ('f1', '<f8'), ('f2', 'S14')])
      
      with open('myfile.dat','w') as f:
          for el in b[()]:
              f.write(str(el)+' ') # or `f.write(repr(el)+' ') to keep the quote marks
      

      这通过使用 [()] 访问 0d 数组的元素来工作:

      >>> b.ndim
      0
      
      >>> b[0]
      IndexError: 0-d arrays cannot be indexed
      
      >>> b[()]
      (1, 2.0, 'buckle_my_shoe')
      

      如果您经常使用零维度的 numpy 数组,为了获得复杂的 dtype,我可能会建议使用 NamedTuple from collections

      >>> import collections
      >>> A = collections.namedtuple('A', ['id', 'val', 'phrase'])
      >>> a = A(1, 2.0, 'buckle_my_shoe')
      
      >>> a
      A(id=1, val=2.0, phrase='buckle_my_shoe')
      >>> a.id
      1
      >>> a.val
      2.0
      >>> a.phrase
      'buckle_my_shoe'
      
      with open('myfile.dat','w') as f:
          for el in a:    
              f.write(repr(el)+' ')
      

      如果数组有多个元素:

      a = np.array([(1, 2.0, 'buckle_my_shoe'),
                    (3, 4.0, 'lock_the_door')],
              dtype=('i4, f8, a14'))
      

      我不确定你希望你的文件是什么样子。如果你想要空格分隔的元组,我认为这是最好的方式:

      with open('myfile.dat','w') as f:
          for row in a:
              f.write(repr(row)+' ')
      

      这会产生如下文件:

      (1, 2.0, 'buckle_my_shoe') (3, 4.0, 'lock_the_door')
      

      也许你不想有逗号或括号,在这种情况下你可以这样做:

      with open('myfile.dat','w') as f:
          for row in a:
              for el in row:
                  f.write(str(el)+' ')
      

      给出这个文件:

      1 2.0 buckle_my_shoe 3 4.0 lock_the_door 
      

      使用repr 将引号保留在字符串周围

      with open('myfile.dat','w') as f:
          for row in a:
              for el in row:
                  f.write(repr(el)+' ')
      

      给出这个文件:

      1 2.0 'buckle_my_shoe' 3 4.0 'lock_the_door' 
      

      奖励:如果您的 dtype 有字段名称,您也可以打印这些名称:

      a.dtype.names = "index value phrase".split()
      a.dtype
      #dtype([('index', '<i4'), ('value', '<f8'), ('phrase', 'S14')])
      
      with open('myfile.dat','w') as f:
          for name in a.dtype.names:
              f.write(name + ' ') # or write(repr(name)) to keep the quote marks
          for row in a:
              for el in row:
                  f.write(repr(el)+' ')
      

      注意,如果您复制这些文件,请注意我使用了'w' 而不是'a',这样我就可以在我的测试用例中覆盖每个文件。

      【讨论】:

      • 很好的答案,但似乎不适用于 0-d 数组。例如。 [f.write(str(el)) for el in a] 给出TypeError: iteration over a 0-d array。不过适用于 >1 行。
      • @atomh33ls 抱歉,这是故意的,因为我认为 0d 数组是一个错误。我把它修好了。
      • @atomh33ls 如果您经常这样做,请注意我建议使用命名元组而不是 0d numpy 数组。
      猜你喜欢
      • 2016-03-18
      • 1970-01-01
      • 1970-01-01
      • 2012-06-21
      • 2016-06-21
      • 2018-12-15
      • 2018-01-01
      • 2016-06-12
      • 2012-03-22
      相关资源
      最近更新 更多