numpy.frombuffer

numpy.frombuffer(bufferdtype=floatcount=-1offset=0)

Interpret a buffer as a 1-dimensional array.

Parameters:
buffer : buffer_like

An object that exposes the buffer interface.

dtype : data-type, optional

Data-type of the returned array; default: float.

count : int, optional

Number of items to read. -1 means all data in the buffer.

offset : int, optional

Start reading the buffer from this offset (in bytes); default: 0.

Notes

If the buffer has data that is not in machine byte-order, this should be specified as part of the data-type, e.g.:

>>>

>>> dt = np.dtype(int)
>>> dt = dt.newbyteorder('>')
>>> np.frombuffer(buf, dtype=dt)

The data of the resulting array will not be byteswapped, but will be interpreted correctly.

Examples

>>>

>>> s = 'hello world'
>>> np.frombuffer(s, dtype='S1', count=5, offset=6)
array(['w', 'o', 'r', 'l', 'd'],
dtype='|S1')
>>>

>>> np.frombuffer(b'\x01\x02', dtype=np.uint8)
array([1, 2], dtype=uint8)
>>> np.frombuffer(b'\x01\x02\x03\x04\x05', dtype=np.uint8, count=3)
array([1, 2, 3], dtype=uint8)

NumPy的ndarray数组对象不能像list一样动态地改变其大小,在做数据采集时很不方便。本文介绍如何通过np.frombuffer()实现动态数组。

列表对象的内存动态分配

Python的列表对象实际上是一个动态指针数组。当列表中没有空间储存新的元素时,列表会动态地改变其大小,以容纳新的元素。每次改变大小时,它都会预留一部分空间,以降低改变大小的频率。下面的程序可以观察列表的这一行为。

import sys
import pylab as pl size = []
for i in xrange(10000):
size.append(sys.getsizeof(size)) pl.plot(size, lw="2")
pl.show()

程序的输出如下图所示,图中每个阶梯跳变的位置都表示一次内存分配,而每个阶梯的高度表示额外分配的内存的大小。

因此由于往列表中添加新元素时,基本上时间复杂度都为O(1),只有在重新分配内存时,时间复杂度才变为O(n)。由于每次额外分配的内存和列表的长度成正比,因此随着列表的增大,重新分配内存的次数会减少,从而整体上append()方法的平均时间复杂度为O(1)。这种动态数组很适合用来做数据采集,然而由于列表中的每个元素都是对象,比较浪费内存,因此用列表做大量数据的采集并不划算。我们希望通过类似NumPy数组的对象采集数据。

NumPy数组的动态分配

NumPy的数组没有这种动态改变大小的功能,numpy.append()函数每次都会重新分配整个数组,并把原来的数组复制到新数组中。下面的程序模拟列表的动态分配,从而实现动态数组:

import numpy as np
class DynamicArray(object):
def __init__(self, item_type):
self._data = np.zeros(10, dtype=item_type)
self._size = 0 def get_data(self):
return self._data[:self._size] def append(self, value):
if len(self._data) == self._size:
self._data = np.resize(self._data, int(len(self._data)*1.25))
self._data[self._size] = value
self._size += 1 item_type = np.dtype({
"names":["id", "x", "y", "z"],
"formats":["i4", "f8", "f8", "f8"]}) da = DynamicArray(item_type) for i in xrange(100):
da.append((i, i*0.1, i*0.2, i*0.3)) data = da.get_data()

用array数组采集数据

Python标准库中的array数组也提供了动态分配内存的功能,而且它和NumPy数组一样直接将数值的二进制数据保存在一块内存中,因此我们可以先用array数组收集数组,然后通过np.frombuffer()将array数组的数据内存直接转换为一个NumPy数组。下面是一个例子:

>>> import numpy as np
>>> from array import array
>>> a = array("d", [1,2,3,4]) # 创建一个array数组
>>> a
array('d', [1.0, 2.0, 3.0, 4.0])
>>> na = np.frombuffer(a, dtype=np.float) # 通过np.frombuffer()创建一个和a共享内存的NumPy数组
>>> na
array([ 1., 2., 3., 4.])
>>> na[1] = 20 # 修改NumPy数组中的第一个元素
>>> a
array('d', [1.0, 20.0, 3.0, 4.0]) # array数组中的第一个元素也同时改变

array数组只支持一维,如果我们需要采集多个频道的数据,可以将这些数据依次添加进array数组,然后通过reshape()方法将np.frombuffer()所创建的NumPy数组改为二维数组。下面是一个例子:

buf = array("d")
for i in range(100):
buf.append(math.sin(i*0.1)) ❶
buf.append(math.cos(i*0.1)) data = np.frombuffer(buf, dtype=np.float).reshape(-1, 2) ❷
print data

在这个例子中,❶我们通过array数组buf采集两个频道的数据,数据采集完毕之后,我们通过np.frombuffer()将其转换为NumPy数组,并通过reshape()将其形状改为(100,2)。

用bytearray采集数据

当每个频道的数据类型不同时,就不能采用上节所介绍的方法了。这时我们可以使用bytearray收集数据。bytearray是字节数组,因此我们首先需要通过struct模块将Python的数值转换成其字节表示形式。如果数据来自二进制文件或者硬件,那么我们得到得已经是字节数据,这个步骤可以省略。下面是使用bytearray进行数据采集的例子:

buf = bytearray()
for i in range(100):
buf.extend(struct.pack("=hdd", i, math.sin(i*0.1), math.cos(i*0.1))) ❶ dtype = np.dtype({"names":["id","sin","cos"], "formats":["h", "d", "d"]}) ❷
data = np.frombuffer(buf, dtype=dtype) ❸
print data

❶采集三个频道的数据,其中频道1是短整型整数,其类型符号为”h”,频道2和3为双精度浮点数,其类型符号为”d”。类型格式字符串中的”=”表示输出得字节数据不进行内存对齐。即一条数据的字节数为2+8+8=16,如果没有”=”,那么一条数据的字节数则为8+8+8=24。

❷定义一个dtype对象表示一条数据的结构,dtype对象缺省不进行内存对齐,如果采集数据用的bytearray中的数据是内存对齐的话,只需要设置dtype()的align参数为True即可。

❸最后通过np.frombuffer()将bytearray转换为NumPy的结构数组。然后我们就可以通过data[“id”]、data[“sin”]和data[“cos”]访问三个频道的数据了。

np.frombuffer()还可以从字符串创建数组,数组也和字符串共享数据内存,但由于字符串是不可变对象,因此所创建的数组是只读的。如果不需要修改数据,这种方法比np.fromstring()更快、更节省内存。

np.frombuffer()的更多相关文章

  1. np.memmap读取大文件

    Numpy中的ndarray是一种新形式的Python内建类型.因此,它可以在需要时被继承.ndarray形成了许多有用类的基础. np.memmap就是其中一种,它是内存映射文件.本质上就是使用C语 ...

  2. 深度学习之 GAN 进行 mnist 图片的生成

    深度学习之 GAN 进行 mnist 图片的生成 mport numpy as np import os import codecs import torch from PIL import Imag ...

  3. 深度学习之 mnist 手写数字识别

    深度学习之 mnist 手写数字识别 开始学习深度学习,先来一个手写数字的程序 import numpy as np import os import codecs import torch from ...

  4. COCO 数据集的使用

    Windows 10 编译 Pycocotools 踩坑记 COCO数据库简介 微软发布的COCO数据库, 除了图片以外还提供物体检测, 分割(segmentation)和对图像的语义文本描述信息. ...

  5. NumPy 超详细教程(1):NumPy 数组

    系列文章地址 NumPy 最详细教程(1):NumPy 数组 NumPy 超详细教程(2):数据类型 NumPy 超详细教程(3):ndarray 的内部机理及高级迭代 文章目录 Numpy 数组:n ...

  6. AI - TensorFlow - 示例01:基本分类

    基本分类 基本分类(Basic classification):https://www.tensorflow.org/tutorials/keras/basic_classification Fash ...

  7. python科学计算库的numpy基础知识,完美抽象多维数组(原创)

    #导入科学计算库 #起别名避免重名 import numpy as np #小技巧:从外往内看==从左往右看 从内往外看==从右往左看 #打印版本号 print(np.version.version) ...

  8. numpy科学计算库的基础用法,完美抽象多维数组(原创)

    #起别名避免重名 import numpy as np #小技巧:print从外往内看==shape从左往右看 if __name__ == "__main__": print(' ...

  9. Kafka+OpenCV 实现实时流视频处理

     1. 启动Kafka Server bin/kafka-server-start.sh config/server.properties & 2. 创建一个新topic bin/kafka- ...

随机推荐

  1. 中点Brehensam画圆算法

    #include<stdio.h> #include<stdlib.h> #include<graphics.h> #include<math.h> v ...

  2. 除了用作缓存数据,Redis还可以做这些

    Redis应该说是目前最受欢迎的NoSQL数据库之一了.Redis通常被作为缓存组件,用作缓存数据.不过,除了可以缓存数据,其实Redis可以做的事还有很多.下面列举几例,供大家参考. 1.最新列表 ...

  3. python selenium 问题汇总

    FAQ 1.python+selenium+Safari浏览器,定位元素 selenium.common.exceptions.ElementNotVisibleException: Message: ...

  4. Codeforces Round #506 D. Concatenated Multiples题解

    一.传送门 http://codeforces.com/contest/1029/problem/D 二.题意 给你$N$个数字$a_1,a_2,\cdots,a_n$,一个$K$,求所有$i \ne ...

  5. 20180129周一之学习PYTHON笔记【安装、查看工作目录、】

    一,安装过程中多选一个ADD的项,免去设置环境变量. 二,PYAUTOGUI模块控制键鼠. IMAGE模块. ----------------------python 如何查看与更换工作目录----- ...

  6. uva-657-搜索

    注意是四个方向(上下左右),不是八个方向,当成了八个方向做,一直wa AC时间:0ms #include<stdio.h> #include<iostream> #includ ...

  7. 生产案例、Linux出现假死,怎么回事?

    1.什么是假死 所谓假死,就是能ping通,但是ssh不上去:任何其他操作也都没反应,包括上面部署的nginx也打不开页面. 2.假死其实很难出现一次 作为一个多任务操作系统,要把系统忙死,忙到ssh ...

  8. vim编程设置

    在终端下使用vim进行编辑时,默认情况下,编辑的界面上是没有显示行号.语法高亮度显示.智能缩进 等功能的.为了更好的在vim下进行工作,需要手动设置一个配置文件:.vimrc.在启动vim时,当前用户 ...

  9. socket编程一些注意的东西

    帮一个同学做了一下面试的作业.主要是socket编程要写一个多人博彩游戏室.没注意,被一些地方坑了一下,而且其实如果没有这个概念,还不好发现. 1.readLine() http://blog.csd ...

  10. redis该怎么用

    最近一些人在介绍方案时,经常会出现redis这个词,于是很多小伙伴百度完redis也就觉得它是一个缓存,然后项目里面把数据丢进去完事,甚至有例如将实体属性拆分塞进redis hash里面的奇怪用法等等 ...