Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
pythonnumpyrecarray:可以使用指针算法获得不同字段的视图吗?_Python_Numpy_Recarray - Fatal编程技术网

pythonnumpyrecarray:可以使用指针算法获得不同字段的视图吗?

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

我有一个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_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