2

对python来说相对较新,如果这有一个我没有找到的明显答案,请原谅。

我正在将一些临时连续的二进制文件读入 numpy 记录数组,最终目标是将它们存储在 pytable 中。我预计的问题是文件可能并不都具有相同的字段或相同的字段顺序。我一直在寻找一个numpy函数,它将使用字段标签或索引对recarray的列(而不是行)进行排序。当您将一个recarray附加到另一个时,更好的是一个为您执行此操作的函数 - 并考虑丢失的列。以下是我想到的示例:

#-------script------------
Myarray1 = np.array([(1,2,3),(1,2,3),(1,2,3)], {'names': ('a','b','c'), 'formats': ('f4', 'f4', 'f4')})
Myarray2 = np.array([(2,1,4,3),(2,1,4,3),(2,1,4,3)], {'names': ('b','a','d','c'), 'formats': ('f4', 'f4', 'f4', 'f4')})
Myarray3 = SomeColumnSortFunction(Myarray2, sortorder=[2,1,4,3])
Myarray4 = SomeBetterVerticalStackFunction(Myarray1,Myarray2)
#
print(Myarray1)
print()
print(Myarray2)
print()
print(Myarray3)
print()
print(Myarray4)

#---------- Wished for Output -------------
[(1.0, 2.0, 3.0) (1.0, 2.0, 3.0) (1.0, 2.0, 3.0)],
 dtype=[('a', 'i4'), ('b', 'i4'), ('c', 'i4')]

[(2.0, 1.0, 4.0, 3.0) (2.0, 1.0, 4.0, 3.0) (2.0, 1.0, 4.0, 3.0)],
dtype=[('b', 'i4'), ('a', 'i4'), ('d', 'i4'), ('c', 'i4')]


[(1.0, 2.0, 3.0, 4.0) (1.0, 2.0, 3.0, 4.0) (1.0, 2.0, 3.0, 4.0)] 
dtype=[('a', 'i4'), ('b', 'i4'), ('c', 'i4'), ('d', 'i4')]

[(1.0, 2.0, 3.0, NaN) (1.0, 2.0, 3.0, NaN) (1.0, 2.0, 3.0, NaN),
 (1.0, 2.0, 3.0, 4.0) (1.0, 2.0, 3.0, 4.0) (1.0, 2.0, 3.0, 4.0)] 
dtype=[('a', 'i4'), ('b', 'i4'), ('c', 'i4'), ('d', 'i4')]
4

2 回答 2

5
  • 如果要重新排序结构化数组的字段,只需使用花哨的索引:

    MyArray3 = MyArray2[['a','b','c','d']]
    

    如果您想使用整数对字段进行排序,您可以使用以下内容:

    order = [1,0,3,2]
    names = MyArray2.dtype.names
    MyArray3 = MyArray2[[names[i] for i in order]]
    

    (在您的 中sortorder=[2,1,4,3],您可能忘记了可迭代的第一个索引是 0...)

  • 对于堆叠结构化数组,请查看numpy.lib.recfunctions子模块,stack_arrays特别是函数。请注意,您必须import numpy.lib.recfunctions明确使用

这是文档字符串

stack_arrays(arrays, defaults=None, usemask=True, asrecarray=False, autoconvert=False)

Superposes arrays fields by fields

Parameters
----------
seqarrays : array or sequence
    Sequence of input arrays.
defaults : dictionary, optional
    Dictionary mapping field names to the corresponding default values.
usemask : {True, False}, optional
    Whether to return a MaskedArray (or MaskedRecords is `asrecarray==True`)
    or a ndarray.
asrecarray : {False, True}, optional
    Whether to return a recarray (or MaskedRecords if `usemask==True`) or
    just a flexible-type ndarray.
autoconvert : {False, True}, optional
    Whether automatically cast the type of the field to the maximum.

Examples
--------
>>> from numpy.lib import recfunctions as rfn
>>> x = np.array([1, 2,])
>>> rfn.stack_arrays(x) is x
True
>>> z = np.array([('A', 1), ('B', 2)], dtype=[('A', '|S3'), ('B', float)])
>>> zz = np.array([('a', 10., 100.), ('b', 20., 200.), ('c', 30., 300.)],
...   dtype=[('A', '|S3'), ('B', float), ('C', float)])
>>> test = rfn.stack_arrays((z,zz))
>>> test
masked_array(data = [('A', 1.0, --) ('B', 2.0, --) ('a', 10.0, 100.0) ('b', 20.0, 200.0)
 ('c', 30.0, 300.0)],
             mask = [(False, False, True) (False, False, True) (False, False, False)
 (False, False, False) (False, False, False)],
       fill_value = ('N/A', 1e+20, 1e+20),
            dtype = [('A', '|S3'), ('B', '<f8'), ('C', '<f8')])
于 2012-09-01T14:18:47.930 回答
0

请注意,@PierreGM的答案似乎不适用于旧版本numpy,例如这个片段:

  python -c 'import numpy as np
from pprint import pformat
print np.__version__
a = np.array([ (1, 4.0, "Hello"), 
               (-1, -1.0, "World")],
       dtype=[("f0", ">i4"), ("f1", ">f4"), ("S2", "|S10")])
print("a : "+ pformat( a ) )
print("a1: "+ pformat( a[["f0", "S2"]] ) )
print("a2: "+ pformat( a[["S2", "f0"]] ) )
'

...为我生成这个(python 2.7):

1.5.1
a : array([(1, 4.0, 'Hello'), (-1, -1.0, 'World')], 
      dtype=[('f0', '>i4'), ('f1', '>f4'), ('S2', '|S10')])
a1: array([(1, 'Hello'), (-1, 'World')], 
      dtype=[('f0', '>i4'), ('S2', '|S10')])
a2: array([(1, 'Hello'), (-1, 'World')], 
      dtype=[('f0', '>i4'), ('S2', '|S10')])

...也就是说,列根本没有重新排列。


编辑:找到了一个替代方案,使用numpy.lib.recfunctions;还索引 — NumPy v1.5 手册(NumPy 参考)结构化数组(又名“记录数组”)— NumPy v1.5 手册(NumPy 用户指南)。基本上:

  • 创建一个新列表,其中包含按您想要的顺序重新排列的列 dtypes
  • 创建一个新的np.arrays via列表.view(以便为每个保留名称和 dtype),代表每一列,根据重新排列的列 dtype 列表重新排序
  • 使用np.arrays 的列表作为参数numpy.lib.recfunctions.merge_arrays

所以这可以添加到这篇文章的前一个片段中:

from numpy.lib import recfunctions as rfn

rdtype=[("S2", "|S10"), ("f1", ">f4"), ("f0", ">i4")]
#ra = np.array( [ np.array(a[rdt[0]], rdt) for rdt in rdtype] )
#print [np.array(a[rdt[0]], dtype=rdt) for rdt in rdtype] # no
#print [np.array(a[rdt[0]]) for rdt in rdtype] #passes, no field names
print [np.array(a[rdt[0]]).view([rdt]) for rdt in rdtype] #ok
ra = rfn.merge_arrays( ( [np.array(a[rdt[0]]).view([rdt]) for rdt in rdtype] ) )
print("a4: "+ pformat( ra ) )

...另外输出:

[array([('Hello',), ('World',)], 
      dtype=[('S2', '|S10')]), array([(4.0,), (-1.0,)], 
      dtype=[('f1', '>f4')]), array([(1,), (-1,)], 
      dtype=[('f0', '>i4')])]

a4: array([('Hello', 4.0, 1), ('World', -1.0, -1)], 
      dtype=[('S2', '|S10'), ('f1', '>f4'), ('f0', '>i4')])

...这最终表明列已按要求重新排列。

好吧,希望这对某人有所帮助-希望这里没有其他问题,
干杯!

于 2013-12-12T02:27:21.503 回答