1

我有一个 numpy 结构化数组a并在其上创建一个视图b

import numpy as np
a = np.zeros(3, dtype={'names':['A','B','C'], 'formats':['int','int','float']})
b = a[['A', 'C']]

descr数据类型的组件表示b数据以某种方式“分散”存储。

>>> b.dtype.descr
[('A', '<i4'), ('', '|V4'), ('C', '<f8')]

(阅读文档后,我认为该组件('', '|V4')表示数据中存在“差距”,这b只是对 . 的看法a。)

如果这让我感到困扰,我可以复制数据:

import numpy.lib.recfunctions as rf
c = rf.repack_fields(b)

>>> c.dtype.descr
[('A', '<i4'), ('C', '<f8')]

如预期的。

这一步需要我复制数据。现在有时,我想对视图应用一个操作。通常,这些操作无论如何都会返回数组的副本。例如,

d = np.concatenate((b,b))

b返回和中数据的副本a。尽管如此,

>>> d.dtype.descr
[('A', '<i4'), ('', '|V4'), ('C', '<f8')]

表示数据没有被有效地存储。

那么有没有办法在不产生“分散”结果的情况下处理视图?我总是必须事先创建一个副本吗?还是没有效率问题,只是以一种奇怪的方式descr描述数据类型?(如果是这样,我怎样才能避免这种情况?)

如果我想忽略中间步骤,这个问题就变得特别重要:

d = np.concatenate((a[['A', 'C']], a[['A', 'C']]))

我正在使用 numpy 1.16 和 python 3.7。

4

2 回答 2

2

多字段索引现在一直处于不断变化的状态。1.16他们似乎已经确定了这种“视图”的“偏移”形式,如果您想要一个“干净”的副本,则需要明确的重新打包。

In [231]: np.__version__                                                             
Out[231]: '1.16.1'
In [232]: a.dtype                                                                    
Out[232]: dtype([('A', '<i8'), ('B', '<i8'), ('C', '<f8')])
In [233]: a[['A','C']].dtype                                                         
Out[233]: dtype({'names':['A','C'], 'formats':['<i8','<f8'], 'offsets':[0,16], 'itemsize':24})

在此视图中,“B”的值仍然存在(偏移量 8)。将数据缓冲区视为具有:

[a0, b0, c0, a1, b1, c1, a2, b2, c2, ....]

[233] 'view' 查看相同的数据缓冲区,但只允许我们访问AandC字段。 repack_fields创建一个新的数据缓冲区:

[a0, c0, a1, c1, ....]

如果a是一个常规(n,3)数组,a[:, [0,2]]将是一个副本。我们不能跳过a[:,1],仍然有一个观点。

In [234]: np.concatenate((a[['A','C']],a[['A','C']]))                                
Out[234]: 
array([(0, 0.), (1, 1.), (2, 2.), (0, 0.), (1, 1.), (2, 2.)],
      dtype={'names':['A','C'], 'formats':['<i8','<f8'], 'offsets':[0,16], 'itemsize':24})

玩弄view我发现偏移量 8 处的字段(中的“B”字段a)仍然存在,但未初始化(如在np.empty数组中)。

显示这种“分散”数据类型的不同方式:

In [238]: a1.dtype                                                                   
Out[238]: dtype({'names':['A','C'], 'formats':['<i8','<f8'], 'offsets':[0,16], 'itemsize':24})

In [239]: a1.dtype.descr                                                             
Out[239]: [('A', '<i8'), ('', '|V8'), ('C', '<f8')]

In [241]: a1.dtype.fields                                                            
Out[241]: mappingproxy({'A': (dtype('int64'), 0), 'C': (dtype('float64'), 16)})

我也可以重新排序字段:

In [248]: a[['B','C','A']].dtype                                                     
Out[248]: dtype({'names':['B','C','A'], 'formats':['<i8','<f8','<i8'], 'offsets':[8,16,0], 'itemsize':24})
In [249]: a[['B','C','A']].dtype.descr                                               
...
ValueError: dtype.descr is not defined for types with overlapping or out-of-order fields
于 2019-04-17T02:05:03.077 回答
0

对于仅连接,您可以简单地执行以下操作:

a     = np.array([(1,2,3),(4,5,6)], 'f,f,f')
view  = a[['f0','f2']]

b     = np.empty(4, 'f,f')
b[:2] = view
b[2:] = view

print(b)

输出:

array([(1., 3.), (4., 6.), (1., 3.), (4., 6.)],
      dtype=[('f0', '<f4'), ('f1', '<f4')])

编辑:忘记我所说的np.add,无论如何它都不应该工作

于 2019-04-17T06:03:03.290 回答