来自Buffer的Numpy 2D-Array?

时间:2016-08-23 04:57:40

标签: python numpy

我有一个内存映射,其中包含一个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

2 个答案:

答案 0 :(得分:1)

我没有多少使用过frombuffer,但我认为np.array与那些数组一样,与传统构造的数组一样。

每个column_data数组都有自己的数据缓冲区 - 您为其分配的mmap。但是np.array(columns)从列表中的每个数组中读取值,并使用自己的数据缓冲区从它们构造一个新数组。

我喜欢使用x.__array_interface__查看数据缓冲区位置(以及查看其他关键属性)。比较columnsdata的每个元素的字典。

您可以使用连续的块从mmap构造一个二维数组。只需制作1d frombuffer数组,然后reshape数组。即使transpose将继续使用该缓冲区(使用F顺序)。切片和视图也使用它。

但除非你真的小心,否则你很快就会获得将数据放在别处的副本。只需data1 = data+1创建一个新数组,或提前编制索引data[[1,3,5],:]。任何concatenation都相同。

来自bytestring buffers的2个数组:

In [534]: x=np.frombuffer(b'abcdef',np.uint8)
In [535]: y=np.frombuffer(b'ghijkl',np.uint8)

加入新数组

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)

x,y,z的数据缓冲区位置完全不同

但重塑x的数据不会改变

In [541]: x.reshape(2,3).__array_interface__['data']
Out[541]: (3013090040, True)

也不是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}

相同数据,不同观点

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')

答案 1 :(得分:0)

假设您有一个字节数组并且您知道它的维度,答案非常简单。 想象一下你在缓冲区中的原始RGB数据(每像素24位)(名为' buff') 尺寸为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)