目录
第一章 NumPy基础
1.1 NumPy数组对象
关键字:array、arange、ndarray、type、dtype、shape、下标
1.2 NumPy数据类型
array、arange指定函数类型
复数的写法及转化规则
1.3 数组元素所占的字节数 a.dtype.itemsize
1.4 字符编码:不推荐使用
1.5 numpy完整的数据类型列表
1.6 定义自己的数据类型
dtype类的属性
1.7 创建自定义数据类型
1.8 一维数组的索引和切片&利用步长-1来翻转数组
1.9 多维数组的切片和索引
reshape创建多维数组
数组元素索引的表示方式a[1,2] or/and a[1][2] 以及列表元素索引
用省略号'...'来表示遍历剩下的维度
使用-1进行多维数组的翻转
1.10 改变数组的维度
使用reshape将数组展平
将数组展平b.ravel()、b.flatten():维度变为(长度,)
用元组设置维度:b.shape=(6,4) 等价于 b=b.reshape(6,4)
矩阵转置 b.transpose() 或者 b.T
b.resize((2,12))功能和reshape(2,12)一样,不同点是,resize会直接改变b的值
1.11 数组的组合(合并)
水平组合:np.hstack((a,b))或者np.concatenate((a,b), axis=1)
垂直组合:np.vstack((a,b))或者 np.concatenate((a,b), axis=0)
深度组合 :np.dstack((a,b))
列组合:column_stack
行组合 row_stack
1.12 数组分割
水平分割 np.split(a,3)分成3份
垂直分割:np.vsplit(a,3)
深度分割 np.dsplit(a, 3)
1.13 数组的属性
维数:b.ndim
元素个数:b.size
数组每个元素在内存中所占字节数:b.itemsize
数组每个元素的数据类型:b.dtype
数组所有元素所占存储空间:b.nbytes 其实就是size*itemsize
转置:b.T或者b.transpose()
复数实部:b.real
复数虚部:b.imag
如果数组中包含复数元素,则其数据类型自动变为复数型
flat属性 :允许我们像遍历一维数组一样去遍历多维数组
1.14 数组的转换:将数组转换为Python列表
转变数组元素的数据类型: b.astype(int)
NumPy中的 ndarray 是一个多维数组对象,该对象由两部分组成:
大部分的数组操作仅仅修改元数据部分,而不改变底层的实际数据
import numpy as np
a=np.arange(5)
print(type(a)) # type 是原生Python自带的
print(a.dtype) # dtype是numpy的,原生Python不含有这个函数
out:
# a的类型是ndarray
int64 # a的数据的类型是64位的整型
NumPy数组一般是同质的(但有一种特殊的数组类型例外,它是异质的),即数组中的所有元素类型必须是一致的。这样有一个好处:如果我们知道数组中的元素均为同一类型,该数组所需的存储空间就很容易确定下来。
NumPy数组的下标也是从0开始的。
print(a)
print(a[0])
print(a.shape)
out:
[0 1 2 3 4]
0
(5,)
使用array创建数组,参数必须是list
m=np.array([np.arange(2),np.arange(2)]) # 参数是列表,列表的每一个元素又是一个数组
print(m)
print(m.shape)
print(m[0][1])
print(m[1][0]) # 指定数组中的某个元素
out:
[[0 1]
[0 1]]
(2, 2) # 维度输出属性是tuple
1
0
Python支持的数据类型有整型、浮点型以及复数型,但这些类型不足以满足科学计算的需求,因此NumPy添加了很多其他的数据类型。在实际应用中,我们需要不同精度的数据类型,它们占用的内存空间也是不同的。在NumPy中,大部分数据类型名是以数字结尾的,这个数字表示其在内存中占用的位数。下面的表格(整理自NumPy用户手册)列出了NumPy中支持的数据类型。这些类型是仅仅numpy的(除了bool),原生Python不含有这些类型。
每一种数据类型均有对应的类型转换函数:函数名就是它的类型名
a = np.array([1,2])
np.float16(a) # float16是numpy的类型,所以前面必须加np
out:
array([1., 2.], dtype=float16)
在NumPy中,许多函数的参数中可以指定数据类型,通常这个参数是可选的
a=np.arange(7, dtype=np.float16) # 任何时候数据类型前不要忘记加np
print(a)
b=np.array([0,1,2,3,4], dtype=np.uint16)
print(b)
out:
[0. 1. 2. 3. 4. 5. 6.]
[0 1 2 3 4]
复数不能转化为整数或浮点数。整数或浮点数可以转化为复数
a = 3+4j
print(type(a))
b = np.complex(3+4j)
print(type(b))
c = np.complex64(3+4j)
print(type(c))
print(c.dtype)
out:
# 从这里不难看出np.complex和原生的Python自带complex函数意义一样
complex64
int(a)
int(b)
out:
TypeError: can't convert complex to int
TypeError: can't convert complex to int
不同点来了,使用np.complex64或np.complex128或np.complex256生成的复数是直接可以变为整型和浮点型的,就是直接取它的实部。但是会有警告产生!!!
np.int8(c) 或 int(c) 或 np.int(c)结果都是:
警告:/home/wu/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:9: ComplexWarning: Casting complex values to real discards the imaginary part
if __name__ == '__main__':
结果:
3
浮点数也是这样:
np.float16(c) 或 float(c) 或 np.folat(c)
警告:/home/wu/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:2: ComplexWarning: Casting complex values to real discards the imaginary part
结果:3.0
总结:当复数是手写的如:3+4j 类型或者 由complex(3+4j)生成的或由 np.complex(3+4j)生成的类型时 都不能直接转化为整型或浮点型。只由使用np.complex64(3+4j)或np.complex128(3+4j)或np.complex256(3+4j)生成时才能转化为对应的整形或浮点型。
a=np.arange(7, dtype=np.float16)
a.dtype.itemsize
out:
2 # 数组a中的每个元素在内存中占两个字节
NumPy可以使用字符编码来表示数据类型,这是为了兼容NumPy的前身Numeric。我不推荐使用字符编码,但有时会用到,因此下面还是列出了字符编码的对应表。读者应该优先使用 dtype对象来明确表示数据类型,而不是这些字符编码
a=np.arange(7, dtype='f')
a
out:
array([0., 1., 2., 3., 4., 5., 6.], dtype=float32)
b=np.arange(7, dtype='D')
b
out:
array([0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j, 4.+0.j, 5.+0.j, 6.+0.j])
np.sctypeDict.keys()
out:
dict_keys(['?', 0, 'byte', 'b', 1, 'ubyte', 'B', 2, 'short', 'h', 3, 'ushort', 'H', 4, 'i', 5, 'uint', 'I', 6, 'intp', 'p', 7, 'uintp', 'P', 8, 'long', 'l', 'L', 'longlong', 'q', 9, 'ulonglong', 'Q', 10, 'half', 'e', 23, 'f', 11, 'double', 'd', 12, 'longdouble', 'g', 13, 'cfloat', 'F', 14, 'cdouble', 'D', 15, 'clongdouble', 'G', 16, 'O', 17, 'S', 18, 'unicode', 'U', 19, 'void', 'V', 20, 'M', 21, 'm', 22, 'bool8', 'Bool', 'b1', 'float16', 'Float16', 'f2', 'float32', 'Float32', 'f4', 'float64', 'Float64', 'f8', 'float128', 'Float128', 'f16', 'complex64', 'Complex32', 'c8', 'complex128', 'Complex64', 'c16', 'complex256', 'Complex128', 'c32', 'object0', 'Object0', 'bytes0', 'Bytes0', 'str0', 'Str0', 'void0', 'Void0', 'datetime64', 'Datetime64', 'M8', 'timedelta64', 'Timedelta64', 'm8', 'int64', 'Int64', 'i8', 'uint64', 'UInt64', 'u8', 'int32', 'Int32', 'i4', 'uint32', 'UInt32', 'u4', 'int16', 'Int16', 'i2', 'uint16', 'UInt16', 'u2', 'int8', 'Int8', 'i1', 'uint8', 'UInt8', 'u1', 'complex_', 'int0', 'uint0', 'single', 'csingle', 'singlecomplex', 'float_', 'intc', 'uintc', 'int_', 'longfloat', 'clongfloat', 'longcomplex', 'bool_', 'unicode_', 'object_', 'bytes_', 'str_', 'string_', 'int', 'float', 'complex', 'bool', 'object', 'str', 'bytes', 'a'])
t=np.dtype('f8') # 'f‘表示浮点型,8表示占的字节数,所以这是一个float64的类型。我们给它定
# 义了一个自己的名字就是’t'
a=np.arange(7, dtype=t)
a.dtype
out:
dtype('float64')
上面我们定义了一个数据类型’t‘,它相当于一个类dtype的实例,我们可以通过它来查看一下类dtype的属性有哪些。
不难看出:char显示了该数据类型t的字符编码‘d',也就是t是双精度浮点数;type显示了t的类型,str含义如下:
类似C语言里面的结构体,定义了一个复合的数据类型。
例如:自定义一个表示商品信息的数据类型:这个类型包含三个部分:一,用一个长度为40个字符的字符串来记录商品名称,用一个32位的整数来记录商品的库存数量,最后用一个32位的单精度浮点数来记录商品价格。
(1)创建数据类型:
t = np.dtype([('name',np.str_, 40), ('numitems', np.int32), ('price', np.float32)])
t
out:
dtype([('name', '
(2) 查看某一字段数据类型
t['name']
out:
dtype('
(3) 利用自定义的数据类型创建数组
itemz = np.array([('Meaning of live DVD', 42, 3.14), ('Butter', 13, 2.72)], dtype=t)
itemz[1]
out:
('Butter', 13, 2.72)
a = np.arange(9)
print(a)
print(a[3:7])
print(a[:7:2]) # 步长为2
print(a[::-1]) # 利用步长-1翻转数组
out:
[0 1 2 3 4 5 6 7 8]
[3 4 5 6]
[0 2 4 6]
[8 7 6 5 4 3 2 1 0]
b = np.arange(24).reshape(2,3,4) # 请注意它的排列方式,这是一个两层的3x4的三维矩阵
print(b.shape)
print(b)
out:
(2, 3, 4)
[[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]]
以前我们总是用a[0][1]这样的方式来表示矩阵a的第一行的第2个元素。但是,再这里我们发现,numpy的矩阵可以直接用a[0,1]这样的方式表示。
a=np.arange(10).reshape(2, 5)
print(a)
print(a[0,1])
print(a[0][1])
#测试三维矩阵b
b[1,0,0]
out:
[[0 1 2 3 4]
[5 6 7 8 9]]
1
1
12
但是,经过测试Python自带的列表(list)不能使用这样a[0,1]的方式,还是只能使用a[0][1]这样的方式。
b[0]等价于b[0, : , : ]等价于 b[0, ...]
结果都是:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
b[::-1] # 两个矩阵前后翻转
out:
array([[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]],
[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]]])
b[:,::-1,:] # 翻转每矩阵的行
out:
array([[[ 8, 9, 10, 11],
[ 4, 5, 6, 7],
[ 0, 1, 2, 3]],
[[20, 21, 22, 23],
[16, 17, 18, 19],
[12, 13, 14, 15]]])
还有一点需注意:resize((a,b))是必须要指明a,b的值的,例如如果要把矩阵展开为一个行向量,reshape(1,-1)它是自动计算个数并展开的,但是resize必须指明a=1,b=24,否则报错。
首先创建两个数组a和b:
horizontal:水平的,横向的
stack:堆放
concatenate:串联
axis:坐标轴
vertical:垂直的
两个矩阵对应的每一对元素组成一个1x2的矩阵
将每一列的元素组合到一块
注意它的意思:水平分割就是拿个刀从左到右沿着水平方向依次切三刀,把数组分成三份
split:分裂,均分
另一种方法:
注意:一维数组的转置是它本身,这也是为什么我们要把一维数组reshape为二维数组的原因。
获取数组元素
flat是一个可以赋值的属性, 对flat属性赋值将导致整个数组的元素都被覆盖
也可以给指定元素赋值