这是一个初学的python问题,最终与内存管理有关。
我正在将一个uint32 numpy数组切成两部分,然后尝试创建一个子数组的uint8视图。请注意,通过创建视图,我的意思是在uint8中重新解释内存中的基础数据,而不是在uint8中转换变量:因此大小会在过程中发生变化。
这是初始数组和视图的一个例子,工作正常:
a=np.array([(1,2,3,4),(5,6,7,8),(9,10,11,12)],np.int32)
a.view(np.int8) # everything is fine
崩溃(c不是硬拷贝,仍然与原始数组绑定):
a=np.array([(1,2,3,4),(5,6,7,8),(9,10,11,12)],np.int32)
c, a= np.split (a,[1],1);
c.view(np.int8) #oups
在创建视图之前抛弃原始数组并没有帮助:
a=np.array([(1,2,3,4),(5,6,7,8),(9,10,11,12)],np.int32)
c, b= np.split (a,[1],1);
del a
c.view(np.int8) #oups
这是我提出的最好的:
a=np.array([(1,2,3,4),(5,6,7,8),(9,10,11,12)],np.int32)
c, a= np.split (a,[1],1);
c=np.copy(c).view(np.uint8) #ok, but really ?!?
有没有更好的方法将数组拆分为2个子数组,以便numpy考虑它们" native",而不复制它们? (当然原始数组会被丢弃)
答案 0 :(得分:1)
在分割或切片之前,将a
视为dtype np.int8
。然后你可以使用
In [219]: c, _ = np.split(a.view(np.int8), [4], 1)
In [220]: c
Out[220]:
array([[1, 0, 0, 0],
[5, 0, 0, 0],
[9, 0, 0, 0]], dtype=int8)
甚至更简单,
In [286]: c = a.view(np.int8)[:, :4]
In [287]: c
Out[287]:
array([[1, 0, 0, 0],
[5, 0, 0, 0],
[9, 0, 0, 0]], dtype=int8)
代替。
答案 1 :(得分:1)
崩溃不是正确的术语。它只是给出了一条错误消息:
ValueError: new type not compatible with array.
忘记'丢弃'原件;拆分产品仍然存在,并使用原始数据缓冲区。
如果你沿着轴0分割了数组,那么视图就可以了。
In [368]: c0.view(np.int8)
Out[368]: array([[1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0]], dtype=int8)
或者原件是order='F'
:
In [369]: a=np.array([(1,2,3,4),(5,6,7,8),(9,10,11,12)],np.int32,order='F')
In [370]: c,b=np.split(a,[1],1)
In [371]: c.view(np.int8)
Out[371]:
array([[1],
[0],
...
[9],
[0],
[0],
[0]], dtype=int8)
如果需要,可以将最后一个重新改为(3,4)。
可视化原始数据缓冲区中数字的布局
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
您要求的观点是:
[ 1,0,0,0, 2, 3, 4, 5,0,0,0, 6, 7, 8, 9,0,0,0, 10, 11, 12]
很高兴将整个事物视为int8
,但不仅仅是点点滴滴。
使用替代方法,您要求将连续块视为字节
[ 1,0,0,0, 2,0,0,0, 3,0,0,0, 4, 5, 6, 7, 8, 9, 10, 11, 12]