Python/numpy
数据类型
[编辑]| 类型全称 | 字符简写(code) | 别名 | 字节大小 | 类型说明 |
|---|---|---|---|---|
| np.bool_ | ? | bool8 | 1 | 布尔型,存储True/False,底层1/0二进制存储 |
| np.int8 | i1 | char / int8 | 1 | 8位有符号整数,值域 [-128, 127] |
| np.uint8 | u1 | ubyte | 1 | 8位无符号整数,值域 [0, 255],图像灰度常用 |
| np.int16 | i2 | short | 2 | 16位有符号整数,值域 [-32768, 32767] |
| np.uint16 | u2 | ushort | 2 | 16位无符号整数,值域 [0, 65535] |
| np.int32 | i4 | intc | 4 | 32位有符号int,等价C int,{insert\_element\_0\_}[-2³¹,2³¹-1] |
| np.uint32 | u4 | uintc | 4 | 32位无符号unsigned int,{insert\_element\_1\_}[0,2³²-1] |
| np.int64 | i8 | longlong / int_ | 8 | 64位有符号长整型,Python默认int映射类型 |
| np.uint64 | u8 | ulonglong | 8 | 64位无符号长整型,{insert\_element\_2\_}[0,2⁶⁴-1] |
| np.intp | iP | ssize_t | 平台相关 | 指针宽度有符号整数,数组索引专用(适配CPU位宽) |
| np.uintp | uP | uintptr_t | 平台相关 | 指针宽度无符号整数,C指针存储适配{insert\_element\_3\_} |
| np.float16 | f2 | half | 2 | 半精度浮点:1符号+5指数+10尾数 |
| np.float32 | f4 | single | 4 | 单精度浮点:1符号+8指数+23尾数,C float |
| np.float64 | f8 | float_ / double | 8 | 双精度浮点:1符号+11指数+52尾数,Python float默认映射 |
| np.float128 | f16 | longdouble | 16(平台) | 扩展高精度浮点数,x86 extended精度 |
| np.complex64 | c8 | csingle | 8 | 64位复数,实部+虚部各1个float32 |
| np.complex128 | c16 | cdouble / complex_ | 16 | 128位复数,实部+虚部各1个float64,Python complex默认 |
| np.bytes_ | S | string_ | 定长n(Sn) | 定长ASCII字节串,S10=最多10字节 |
| np.str_ | U | unicode_ | 定长n(Un) | 定长Unicode字符,U10=最多10个UTF32字符 |
| np.object_ | O | object | 8/平台 | Python对象指针,任意Python对象装箱存储 |
| np.void | V | void | 自定义N(VN) | 原始二进制裸字节块,用于自定义C-struct内存布局 |
| np.datetime64 | M | — | 4/8 | 日历日期时间,可指定单位(D/h/min/s) |
| np.timedelta64 | m | — | 4/8 | 时间间隔,两个datetime差值存储 |
注释:平台依赖类型int_/intp/longdouble 在 32/64 位系统字节长度不同,对接 C 代码优先用固定位宽i1/i2/i4/i8;
结构化 Dtype
[编辑]数据类型对象(Data Type Object)又称 dtype 对象,主要用来描述数组元素的数据类型、大小以及字节顺序。同时,它也可以用来创建结构化数据。这是numpy的扩展功能,不属于 “数值矩阵” 的范畴,用于:
- 二进制协议解析
- C语言struct互通
- 读取二进制数据
- 固定格式报文
#定义字段名score,以及数组数据类型i1
dt = np.dtype([('score','i1')])
a = np.array([(55,),(75,),(85,)], dtype = dt)
print(a)
print(a.dtype)
print(a['score'])
#输出结果:
#获取a数组:
[(55,) (75,) (85,)]
#数据类型对象dtype
dtype([('score', 'i1')])
#获取'score'字段分数
[55 75 85]
可以自定结构化Dtype类型,作为数组/矩阵的元素的类型。
| 构造语法分类 | 书写范例 | 核心特性 | 适用场景 |
|---|---|---|---|
| 字段列表元组写法(标准常用) | [("id","i4"),("score","i1"),("val","f4")]
|
依次:(字段名,类型);可加第三参数shape定义内嵌子数组 | 常规结构体定义,日常开发首选 |
| 紧凑字符串简写 | "i4,i1,f4" / "i4,3f4"
|
自动命名字段 f0,f1,f2;数字代表子数组长度 | 快速测试、临时简易结构 |
| names+formats 基础字典 | {"names":["id","score"],"formats":["i4","i1"]}
|
分离字段名与类型,可读性优于字符串 | 需要批量动态生成字段 |
| 精细控偏移字典(含offsets/itemsize/titles/align) | {"names":["id","score"],
"formats":["i4","i1"],
"offsets":[0,8],
"itemsize":12,
"titles":["编号","得分"]}
|
手动指定字节偏移、结构体总大小、字段别名;搭配align=True开启C结构体内存对齐Padding | 对接C原生struct二进制、自定义内存排布 |
| 内嵌子数组字段定义 | [("vec","f4",(3,)),("mat","i1",(2,2))]
|
单个字段内部为固定维度数组,等效C内嵌数组 float vec[3]
|
向量、矩阵类成员的结构体 |
| 嵌套结构体(struct嵌套struct) | [("uid","u4"),("info",[("age","i1"),("h","f4")])]
|
某一字段的dtype本身又是复合结构化dtype,C嵌套struct | 分层复杂数据结构 |
| void 外层封装整块二进制 | ("V16", [("a","i4"),("b","f4")])
|
整体结构体封装为N字节void裸二进制块 | 自定义二进制报文、协议解析 |
| CTypes结构体自动映射 | class S(ctypes.Structure):
_fields_=[("id",ctypes.c_int32),("s",ctypes.c_int8)]
dt=np.dtype(S)
|
从C语言struct一键生成numpy dtype,内存布局完全对齐 | C/C++与Numpy二进制互通开发 |
数组
[编辑]NumPy数组类似于Python列表。它们都可以用作容器,具有获取(getting)和设置(setting)元素以及插入和移除元素的功能。Python列表用树实现。Numpy数组用C语言数组实现,更紧凑,尤其是在一维以上的维度;向量化操作时比Python列表快,但在末尾添加元素比Python列表慢。
用法
[编辑]NumPy数组类似于Python列表用法略有区别:
a=[1,2,3]
b=[4,5,6]
[q*2 for q in a]
[q+r for q,r in zip(a,b)]
a=np.array([1,2,3])
b=np.array([4,5,6])
a*2
a+b
数组生成
[编辑]NumPy数组无法像Python列表那样加长,因为在数组末尾没有保留空间。因此,常见的做法是定义一个Python列表,对它进行操作,然后再转换为NumPy数组,或者用np.zeros和np.empty初始化数组,预分配必要的空间。
a=np.array([1,2,3])
b=np.zeros(3,int)
c=np.ones(3,int)
d=np.empty(3)
e=np.full(3,7)
f=np.zeros_like(a)
g=np.ones_like(a)
h=np.empty_like(a)
i=np.arange(2,9,2) #Out: array([2, 4, 6, 8]); arange means Array Range
np.linspace(2.0, 3.0, num=5)# output: array([2. , 2.25, 2.5 , 2.75, 3. ])
np.random.randint(0,10,3) # uniform in [0,10). Caution: random.randint is in [0,10]
np.random.uniform(1, 10,3)
np.random.randn(3) # standard normal distribution
np.random.normal(5,2,3) #normal, mu=5, sigma=2
数组访问
[编辑]数组的索引基于0.
索引为-1的元素为数组首元素的左侧元素,即数组尾元素。因此,a[-2:]即数组的尾部两个元素。
索引范围可用 begin:end 形式或者 begin:end:step形式,其中的begin、end都可以省略采用缺省值
索引也可以表示为一个list,如a1,3,4表示取数组a的第2、4、5号元素。
数组的赋值,如b=a, c=a[:]都是原数组的view,只有 d=a.copy()才是复制一份。
也可以用布尔索引。例如 a[a>5]
np.ndenumerate类构造了数组的迭代器。每次迭代返回索引与值的组合。
获取满足条件的数组元素的索引,可用用np.where()函数或等效的np.nonzero()函数。为了获取满足条件的多维数组元素的索引,可用np.transpose(np.nonzero(x>1))或等效的np.where(x>1)
np.where()函数的更高级用法,使用三个参数condition、x、y,表示如果条件满足,就取array_like的x的对应元素替换,否则取y的对应元素替换。
np.clip()函数对一个数组给定一个interval如[a,b],数组中值小于a的元素被赋值为a,值大于b的元素被赋值为b。
数组的运算
[编辑]数组可以与标量运算,也可以与另一个数组运算。
和Python中一样,a//b表示div b(整除),x**n表示xⁿ
向量的点积可以用np.dot()函数,也可以用运算符@, 如 a@b
向量的叉积可以用np.cross()函数
数组的成员函数可以做的运算:max、min、argmax、argmin、sum、var、mean、std、sort(原地排序)、
np.searchsorted()函数对已排序数组搜索一个值的第一次出现的索引。
浮点数比较,使用np.allclose()函数。可以指定相对公差参数rtol或绝对公差参数atol。
多维数组
[编辑]NumPy ndarray矩阵(多维数组)的本意:单一数据类型 + 纯数值 + 连续整块内存。用于纯数值计算(线性代数、矩阵运算、卷积、图像处理),速度接近C语言。
与一维数组相比,多维数组的新概念如下。
eyes()用于生成单位阵。
NumPy引入了axis的概念。对第i个轴,如x.sum(axis=1),表示保持其他索引,对第i个索引的遍历求累计值。
多维数组的运算符,除了@是矩阵乘法,其他均为element-wise。二维操作运算中,行向量和列向量被不同地对待。默认情况下,一维数组在二维操作中被视为行向量。因此,行向量的shape,是(n,)即(1,n)。
矩阵的转置,如x.T
一维数组生成二位数组可以使用reshape函数或newaxis建立新索引,都是原数组的view。例如a是一维数组,a.reshape(-1,1)等效于a[:,None],相当于行向量变为列向量。其中-1表示reshape自动计算该维度上的长度;方括号中的None充当np.newaxis的快捷方式,即在指定位置添加了一个空axis。
因此,NumPy中总共有三种类型的向量:一维数组,二维行向量和二维列向量。后二者转化为一维数组,可以用成员函数flatten()或reshape(-1)。根据规则,一维数组被隐式解释为二维行向量,因此通常不必在这两个数组之间进行转换,但一维数组的转置T操作结果还是原数组。
矩阵的堆叠或叫做连接,使用np.hstack与np.vstack()。矩阵与一维数字的水平堆叠,也可以用np.column_stack()。np.append()也可以对行或列追加。堆叠的逆操作是分裂:np.hsplit()与np.vsplit
矩阵可以通过两种方式完成复制:tile类似于分块矩阵的复制粘贴,repeat类似于逐行或逐列的复制。
特定的列和行可以用np.delete()删除。逆运算为np.insert()函数