我有一个内存映射,其中包含一个 2D 数组,我想从中创建一个 numpy 数组。理想情况下,我想避免复制,因为涉及的数组可能很大。
我的代码如下所示:
n_bytes = 10000
tagname = "Some Tag from external System"
map = mmap.mmap(-1, n_bytes, tagname)
offsets = [0, 5000]
columns = []
for offset in offsets:
#type and count vary in the real code, but for this dummy code I simply made them up. But I know the count and type for every column.
np_type = np.dtype('f4')
column_data = np.frombuffer(map, np_type, count=500, offset=offset)
columns.append(column_data)
# this line seems to copy the data, which I would like to avoid
data = np.array(columns).T
Run Code Online (Sandbox Code Playgroud)
假设您有一个字节数组并且您知道它的尺寸,那么答案非常简单。想象一下,缓冲区(名为“buff”)中图像的原始 RGB 数据(每像素 24 位)尺寸为 1024x768
#read the buffer into 1D byte array
arr = numpy.frombuffer(buff, dtype=numpy.uint8)
#now shape the array as you please
arr.shape = (768,1024,3)
Run Code Online (Sandbox Code Playgroud)
我没有使用frombuffer太多,但我认为np.array这些数组的工作方式与传统构造的数组一样。
每个column_data数组都有自己的数据缓冲区 - 您分配给它的 mmap。但是np.array(columns)从列表中的每个数组中读取值,并用它们自己的数据缓冲区构造一个新数组。
我喜欢用它x.__array_interface__来查看数据缓冲区位置(并查看其他关键属性)。比较该字典中的每个元素columns和 for data。
您可以使用连续的块从 mmap 构造二维数组。只需制作一维frombuffer数组即可reshape。Eventranspose将继续使用该缓冲区(按F顺序)。切片和视图也使用它。
但除非您非常小心,否则您很快就会得到将数据放在其他地方的副本。简单地data1 = data+1创建一个新数组,或者提前索引data[[1,3,5],:]。对于任何 都一样concatenation。
来自字节串缓冲区的 2 个数组:
In [534]: x=np.frombuffer(b'abcdef',np.uint8)
In [535]: y=np.frombuffer(b'ghijkl',np.uint8)
Run Code Online (Sandbox Code Playgroud)
通过加入它们来创建一个新数组
In [536]: z=np.array((x,y))
In [538]: x.__array_interface__
Out[538]:
{'data': (3013090040, True),
'descr': [('', '|u1')],
'shape': (6,),
'strides': None,
'typestr': '|u1',
'version': 3}
In [539]: y.__array_interface__['data']
Out[539]: (3013089608, True)
In [540]: z.__array_interface__['data']
Out[540]: (180817384, False)
Run Code Online (Sandbox Code Playgroud)
的数据缓冲区位置x,y,z完全不同
但重塑后的数据x并没有改变
In [541]: x.reshape(2,3).__array_interface__['data']
Out[541]: (3013090040, True)
Run Code Online (Sandbox Code Playgroud)
2d 也不转置
In [542]: x.reshape(2,3).T.__array_interface__
Out[542]:
{'data': (3013090040, True),
'descr': [('', '|u1')],
'shape': (3, 2),
'strides': (1, 3),
'typestr': '|u1',
'version': 3}
Run Code Online (Sandbox Code Playgroud)
相同的数据,不同的视图
In [544]: x
Out[544]: array([ 97, 98, 99, 100, 101, 102], dtype=uint8)
In [545]: x.reshape(2,3).T
Out[545]:
array([[ 97, 100],
[ 98, 101],
[ 99, 102]], dtype=uint8)
In [546]: x.reshape(2,3).T.view('S1')
Out[546]:
array([[b'a', b'd'],
[b'b', b'e'],
[b'c', b'f']],
dtype='|S1')
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9259 次 |
| 最近记录: |