pythonnumpyrecarray:可以使用指针算法获得不同字段的视图吗?
我有一个numpy结构化数组,其形式如下:pythonnumpyrecarray:可以使用指针算法获得不同字段的视图吗?,python,numpy,recarray,Python,Numpy,Recarray,我有一个numpy结构化数组,其形式如下: x = np.array([(1,2,3)]*2, [('t', np.int16), ('x', np.int8), ('y', np.int8)]) 现在我想在这个数组中生成视图,将't'与'x'或'y'组合在一起。通常的语法会创建一个副本: v_copy = x[['t', 'y']] v_copy #array([(1, 3), (1, 3)], # dtype=[('t', '<i2'), ('y', '|i1')]) v
x = np.array([(1,2,3)]*2, [('t', np.int16), ('x', np.int8), ('y', np.int8)])
现在我想在这个数组中生成视图,将't'
与'x'
或'y'
组合在一起。通常的语法会创建一个副本:
v_copy = x[['t', 'y']]
v_copy
#array([(1, 3), (1, 3)],
# dtype=[('t', '<i2'), ('y', '|i1')])
v_copy.base is None
#True
我们可以找出必要的步骤:
v = np.recarray((2,2), [('b', np.int8)], buf=x, strides=(4,3))
v
#rec.array([[(1,), (3,)],
# [(1,), (3,)]],
# dtype=[('b', '|i1')])
v.base is x
#True
显然,v
指向内存中的正确位置,而没有创建副本。不幸的是,numpy不允许我将这些内存位置重新解释为原始数据类型:
v_view = v.view([('t', np.int16), ('y', np.int8)])
#ValueError: new type not compatible with array.
有没有办法欺骗numpy执行此强制转换,以便创建一个与
v_copy
等效的数组v_view
,但不创建副本?可能直接在v.\uuuu数组\u接口\uuuuuuuuuuuuuuuuuuuuuuuuuu上工作,就像在np.lib.stride\u技巧中所做的那样。您可以这样构造一个合适的数据类型
dt2 = np.dtype(dict(names=('t', 'x'), formats=(np.int16, np.int8), offsets=(0, 2)))
然后呢
y = np.recarray(x.shape, buf=x, strides=x.strides, dtype=dt2)
在未来的Numpy版本(>1.6)中,您也可以这样做
dt2 = np.dtype(dict(names=('t', 'x'), formats=(np.int16, np.int8), offsets=(0, 2), itemsize=4))
y = x.view(dt2)
这适用于numpy 1.6.x,并避免创建重新排列
:
dt2 = {'t': (np.int16, 0), 'y': (np.int8, 3)}
v_view = np.ndarray(x.shape, dtype=dt2, buffer=x, strides=x.strides)
v_view
#array([(1, 3), (1, 3)],
# dtype=[('t', '<i2'), ('', '|V1'), ('y', '|i1')])
v_view.base is x
#True
class arrayview(np.ndarray):
def __new__(subtype, x, fields):
dtype = {f: x.dtype.fields[f] for f in fields}
return np.ndarray.__new__(subtype, x.shape, dtype,
buffer=x, strides=x.strides)
v_view = arrayview(x, ('t', 'y'))
v_view
#arrayview([(1, 3), (1, 3)],
# dtype=[('t', '<i2'), ('', '|V1'), ('y', '|i1')])
v_view.base is x
#True
伟大的因此,我忽略了数据类型可以用偏移量定义。。。您的第一个版本带有np.recarray
可用于['t','x']
和['t','y']
视图。第二种(更优雅的)方法适用于偏移量=(0,3)
(['t','y']
),但不适用于偏移量=(0,2)
(['t','x']
)。我专门从numpy 1.6.1升级到1.6.2,但没有效果。你知道为什么offsets=(0,2)
案例对我不起作用吗?itemsize
关键字是在Numpy>1.6(即当前的开发版本)中添加的,因此在1.6.2中,你会得到一个itemsize与数组大小不兼容的数据类型。谢谢!我用NUMPY1.8dev测试了这个,它可以正常工作。但是,我还没有准备好切换到开发版本,因为它需要重新编译所有模块。所以我做了更多的研究,发现使用np.ndarray
构造函数也可以达到同样的效果。我将此作为单独的答案发布。
class arrayview(np.ndarray):
def __new__(subtype, x, fields):
dtype = {f: x.dtype.fields[f] for f in fields}
return np.ndarray.__new__(subtype, x.shape, dtype,
buffer=x, strides=x.strides)
v_view = arrayview(x, ('t', 'y'))
v_view
#arrayview([(1, 3), (1, 3)],
# dtype=[('t', '<i2'), ('', '|V1'), ('y', '|i1')])
v_view.base is x
#True