Numpy简介
numpy其实就是一个python的拓展库,它支持大量的维度数组与矩阵运算,同时还提供了很多的数学函数库。
Numpy环境安装
在你的pycharm的终端输入以下内容(通常使用第二种方式,在国内的一些镜像网站上下载例如清华、中科院等)
pip install numpy
或
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple numpy
Numpy Ndarray对象
ndarray其实是一个n维数组对象,它是一系列同类型数据的集合,以0为起始下标。
ndarray对象是用于存放同类型元素的多维数组,其中的每个元素在内存中都有相同存储大小的区域
ndarray对象的内部由以下内容组成:
- 一个指向数据(内存或内存映射文件中的一块数据)的指针。
- 数据类型或 dtype,描述在数组中的固定大小值的格子。
- 一个表示数组形状(shape)的元组,表示各维度大小的元组。
- 一个跨度元组(stride),其中的整数指的是为了前进到当前维度下一个元素需要"跨过"的字节数。
跨度可以是负数,这样会使数组在内存中后向移动,切片中 obj[::-1] 或 obj[:,::-1] 就是如此。
创建一个ndarray对象只需要调用numpy库中的array函数即可。
#首先导入numpy库
import numpy as np #as np 是为numpy取一个别名
arr = np.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)
参数说明:
名称 | 描述 |
---|---|
object | 数组或嵌套的数列 |
dtype | 数组元素的数据类型,可选 |
copy | 对象是否需要复制,可选 |
order | 创建数组的内存存储样式,C为行方向,F为列方向,A为任意方向(默认) |
subok | 默认返回一个与基类类型一致的数组 |
ndmin | 指定生成数组的最小维度 |
创建一个维度的数组
import numpy as np
arr = np.array([2,5,3])
print(arr)#结果为[2 5 3]
创建二维数组
import numpy as np
arr = np.array([[1,2,3,4],[5,6,7,8]])
print(arr)
"""
结果为:
[[1 2 3 4]
[5 6 7 8]]
"""
ps:看是几维数组,其实就看array函数小括号中最左端(右端)有几个方括号就可以了,有一个就是一维数组、两个就是二维数组。
最小维度:
其实就是ndarray对象的一个属性(ndmin)
import numpy as np
arr = np.array([[1,2,3],[4,5,6],[7,8,9]],ndmin=3)
print(arr)
"""
[[[1 2 3]
[4 5 6]
[7 8 9]]]
在结果中我们可以看到,我们原本要创建的数组只是一个二维数组,但是通过ndmin属性就将二维数组升维成了三维数组
"""
#思考我们可以通过ndmin属性将二维数组降为一维数组吗
#答案是不可以
arr = np.array([[1,2,3],[4,5,6],[7,8,9]],ndmin=1)
print(arr)
"""
[[1 2 3]
[4 5 6]
[7 8 9]]
在运行的结果我们可以看到,数组还是一个二维数组。
"""
dtype参数
该参数其实就是用来指定数组中有每个元素的数据类型
import numpy as np
a = np.array([1, 2, 3], dtype = complex)
print (a)#[1.+0.j 2.+0.j 3.+0.j]
Numpy数据类型
名称 | 描述 |
---|---|
bool_ | 布尔型数据类型(True 或者 False) |
int_ | 默认的整数类型(类似于 C 语言中的 long,int32 或 int64) |
intc | 与 C 的 int 类型一样,一般是 int32 或 int 64 |
intp | 用于索引的整数类型(类似于 C 的 ssize_t,一般情况下仍然是 int32 或 int64) |
int8 | 字节(-128 to 127) |
int16 | 整数(-32768 to 32767) |
int32 | 整数(-2147483648 to 2147483647) |
int64 | 整数(-9223372036854775808 to 9223372036854775807) |
uint8 | 无符号整数(0 to 255) |
uint16 | 无符号整数(0 to 65535) |
uint32 | 无符号整数(0 to 4294967295) |
uint64 | 无符号整数(0 to 18446744073709551615) |
float_ | float64 类型的简写 |
float16 | 半精度浮点数,包括:1 个符号位,5 个指数位,10 个尾数位 |
float32 | 单精度浮点数,包括:1 个符号位,8 个指数位,23 个尾数位 |
float64 | 双精度浮点数,包括:1 个符号位,11 个指数位,52 个尾数位 |
complex_ | complex128 类型的简写,即 128 位复数 |
complex64 | 复数,表示双 32 位浮点数(实数部分和虚数部分) |
complex128 | 复数,表示双 64 位浮点数(实数部分和虚数部分) |
Numpy数组属性
NumPy 的数组中比较重要 ndarray 对象属性有:
属性 | 说明 |
---|---|
ndarray.ndim | 秩,即轴的数量或维度的数量 |
ndarray.shape | 数组的维度,对于矩阵,n 行 m 列 |
ndarray.size | 数组元素的总个数,相当于 .shape 中 n*m 的值 |
ndarray.dtype | ndarray 对象的元素类型 |
ndarray.itemsize | ndarray 对象中每个元素的大小,以字节为单位 |
ndarray.flags | ndarray 对象的内存信息 |
1、ndarray.ndim
该属性用于返回数组的维度,等于秩
import numpy as np
arr = np.array([[1, 4, 7, 6], [2, 4, 6, 8]])
print(arr.ndim)#结果为2
2、ndarray.shape(重要)
该属性表示可以表示数组的维度,返回的是一个元组,这个元组的长度就是数组的维度。
该属性也可以用于调整数组的形状。
import numpy as np
arr = np.array([[1,2,3,4,5,6,7,8,9],[9,8,7,6,5,4,3,2,1]])
print(arr.shape)#(2, 9)
print(arr)
arr.shape = (2,3,3)
print(arr)
"""
在没有修改shape属性之前
[[1 2 3 4 5 6 7 8 9]
[9 8 7 6 5 4 3 2 1]]
在修改shape属性之后
[[[1 2 3]
[4 5 6]
[7 8 9]]
[[9 8 7]
[6 5 4]
[3 2 1]]]
"""
ps:NumPy 也提供了 reshape 函数来调整数组大小
但是reshape函数返回的是一个新的数组
import numpy as np
arr = np.array([[2,3,5],[4,7,9]])
b = arr.reshape(3,2)
print(arr)
print(b)
"""
arr:
[[2 3 5]
[4 7 9]]
b:
[[2 3]
[5 4]
[7 9]]
我们可以清楚的看到在arr调用reshape函数之后,arr本身并没有发生改变。其原因就是其返回的是一个新的数组
"""
Numpy创建数组
ndarray 数组除了可以使用底层 ndarray 构造器来创建外,也可以通过以下几种方式来创建。
1、numpy.empty
该方法可以用来创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组
ps:未初始化的意思是数组内的值是随机的
numpy.empty(shape, dtype = float, order = 'C')
参数说明:
参数 | 描述 |
---|---|
shape | 数组形状 |
dtype | 数据类型,可选 |
order | 有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。 |
import numpy as np
arr = np.empty(shape=(2,3),dtype=np.uint8)
print(arr)
"""
[[ 97 32 112]
[111 115 105]]
"""
2、numpy.zeros
看到该方法的名字我们大概就可以知道该方法执行后数组中填充的元素都为0
创建指定大小的数组,数组元素以 0 来填充:
numpy.zeros(shape, dtype = float, order = 'C')
参数说明:
参数 | 描述 |
---|---|
shape | 数组形状 |
dtype | 数据类型,可选 |
order | ‘C’ 用于 C 的行数组,或者 ‘F’ 用于 FORTRAN 的列数组 |
import numpy as np
arr = np.zeros(shape=(3,3,3),dtype=np.uint8)
print(arr)
"""
[[[0 0 0]
[0 0 0]
[0 0 0]]
[[0 0 0]
[0 0 0]
[0 0 0]]
[[0 0 0]
[0 0 0]
[0 0 0]]]
"""
ps:注意如果不指定dtype,其默认为浮点数
3、numpy.ones
和numpy.zeros类似,只不过元素用1来填充,dtype的默认值也同样是浮点数
arr = np.ones(shape=(5,2),dtype=np.uint16)
print(arr)
"""
[[1 1]
[1 1]
[1 1]
[1 1]
[1 1]]
"""
4、numpy.zeros_like
该方法用于创建一个与给定数组具有相同形状的数组,数组元素以0来填充。
参数说明:
参数 | 描述 |
---|---|
a | 给定要创建相同形状的数组 |
dtype | 创建的数组的数据类型 |
order | 数组在内存中的存储顺序,可选值为 ‘C’(按行优先)或 ‘F’(按列优先),默认为 ‘K’(保留输入数组的存储顺序) |
subok | 是否允许返回子类,如果为 True,则返回一个子类对象,否则返回一个与 a 数组具有相同数据类型和存储顺序的数组 |
shape | 创建的数组的形状,如果不指定,则默认为 a 数组的形状。 |
arr1 = np.array([[2,3,4],[3,5,7],[9,6,0]])
arr2 = np.zeros_like(arr1)
print(arr1)
print(arr2)
print(type(arr1[0][0]))
print(type(arr2[0][0]))
"""
[[2 3 4]
[3 5 7]
[9 6 0]]
[[0 0 0]
[0 0 0]
[0 0 0]]
<class 'numpy.int64'>
<class 'numpy.int64'>
我们可以看到两个数组的形状都是相同的,数据类型也是相同的
"""
arr1 = np.array([[2,3,4],[3,5,7],[9,6,0]])
arr2 = np.zeros_like(arr1,dtype=np.uint16)
print(arr1)
print(arr2)
print(type(arr1[0][0]))
print(type(arr2[0][0]))
"""
[[2 3 4]
[3 5 7]
[9 6 0]]
[[0 0 0]
[0 0 0]
[0 0 0]]
<class 'numpy.int64'>
<class 'numpy.uint16'>
在我们修改了arr2的dtype之后,我们两个数组中的元素类型就不一样了
"""
5、numpy.ones_like
numpy.ones_like 用于创建一个与给定数组具有相同形状的数组,数组元素以 1 来填充。
该方法的作用与numpy.zeros_like类似,在此就不过多赘述。
6、NumPy 从已有的数组创建数组
1、numpy.asarray
numpy.asarray 类似 numpy.array,但 numpy.asarray 参数只有三个,比 numpy.array 少两个
numpy.asarray(a, dtype = None, order = None)
参数说明:
参数 | 描述 |
---|---|
a | 任意形式的输入参数,可以是,列表, 列表的元组, 元组, 元组的元组, 元组的列表,多维数组 |
dtype | 数据类型,可选 |
order | 可选,有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。 |
arr1 = np.array([[1,2,3,4,5],[5,4,3,2,1]])
arr2 = np.asarray(arr1)
print(arr1)
print(arr2)
"""
[[1 2 3 4 5]
[5 4 3 2 1]]
[[1 2 3 4 5]
[5 4 3 2 1]]
"""
ps:我们同样可以在asarray中指定数组的数据类型
2、numpy.fromiter
numpy.fromiter 方法从可迭代对象中建立 ndarray 对象,返回一维数组。
numpy.fromiter(iterable, dtype, count=-1)
参数 | 描述 |
---|---|
iterable | 可迭代对象 |
dtype | 返回数组的数据类型 |
count | 读取的数据数量,默认为-1,读取所有数据 |
list = [1,2,3,4,5]
it = iter(list)
arr = np.fromiter(it,dtype=np.uint16)
print(arr)#[1 2 3 4 5]
ps:该函数使用时必须指定数组的数据类型
7、NumPy 从数值范围创建数组
1、numpy.arange
numpy 包中的使用 arange 函数创建数值范围并返回 ndarray 对象,函数格式如下:
numpy.arange(start, stop, step, dtype)
arange函数类似与python内嵌的range函数,只不过相当于range函数的一个升级版本。
调用该函数根据 start 与 stop 指定的范围以及 step 设定的步长,生成一个 ndarray。
参数 | 描述 |
---|---|
start | 起始值,默认为0 |
stop | 终止值(不包含) |
step | 步长,默认为1 |
dtype | 返回ndarray 的数据类型,如果没有提供,则会使用输入数据的类型。 |
arr = np.arange(1,10,1,np.uint16)
print(arr)
arr = np.arange(2,9,3,np.uint16)
print(arr)
arr = np.arange(9,dtype=np.uint16)
print(arr)
arr = np.arange(5)
print(arr)
arr = np.arange(9,1,-1,np.uint16)
print(arr)
"""
[1 2 3 4 5 6 7 8 9]
[2 5 8]
[0 1 2 3 4 5 6 7 8]
[0 1 2 3 4]
[9 8 7 6 5 4 3 2]
"""
ps:我们在生成数组之后可以通过修改shape属性改变数组的形状或者通过reshape函数修改数组的形状
2、numpy.linspace
numpy.linspace 函数用于创建一个一维数组,数组是一个等差数列构成的,格式如下
np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
参数说明:
参数 | 描述 |
---|---|
start | 序列的起始值 |
stop | 序列的终止值,如果endpoint 为true ,该值包含于数列中 |
num | 要生成的等步长的样本数量,默认为50 |
endpoint | 该值为 true 时,数列中包含stop 值,反之不包含,默认是True。 |
retstep | 如果为 True 时,生成的数组中会显示间距,反之不显示。 |
dtype | ndarray 的数据类型 |
arr = np.linspace(10,1000)
print(arr)
"""
[ 10. 11.83673469 13.67346939 15.51020408 17.34693878
19.18367347 21.02040816 22.85714286 24.69387755 26.53061224
28.36734694 30.20408163 32.04081633 33.87755102 35.71428571
37.55102041 39.3877551 41.2244898 43.06122449 44.89795918
46.73469388 48.57142857 50.40816327 52.24489796 54.08163265
55.91836735 57.75510204 59.59183673 61.42857143 63.26530612
65.10204082 66.93877551 68.7755102 70.6122449 72.44897959
74.28571429 76.12244898 77.95918367 79.79591837 81.63265306
83.46938776 85.30612245 87.14285714 88.97959184 90.81632653
92.65306122 94.48979592 96.32653061 98.16326531 100. ]
"""
arr = np.linspace(10,100,num=100)
print(arr)
"""
[ 10. 10.90909091 11.81818182 12.72727273 13.63636364
14.54545455 15.45454545 16.36363636 17.27272727 18.18181818
19.09090909 20. 20.90909091 21.81818182 22.72727273
23.63636364 24.54545455 25.45454545 26.36363636 27.27272727
28.18181818 29.09090909 30. 30.90909091 31.81818182
32.72727273 33.63636364 34.54545455 35.45454545 36.36363636
37.27272727 38.18181818 39.09090909 40. 40.90909091
41.81818182 42.72727273 43.63636364 44.54545455 45.45454545
46.36363636 47.27272727 48.18181818 49.09090909 50.
50.90909091 51.81818182 52.72727273 53.63636364 54.54545455
55.45454545 56.36363636 57.27272727 58.18181818 59.09090909
60. 60.90909091 61.81818182 62.72727273 63.63636364
64.54545455 65.45454545 66.36363636 67.27272727 68.18181818
69.09090909 70. 70.90909091 71.81818182 72.72727273
73.63636364 74.54545455 75.45454545 76.36363636 77.27272727
78.18181818 79.09090909 80. 80.90909091 81.81818182
82.72727273 83.63636364 84.54545455 85.45454545 86.36363636
87.27272727 88.18181818 89.09090909 90. 90.90909091
91.81818182 92.72727273 93.63636364 94.54545455 95.45454545
96.36363636 97.27272727 98.18181818 99.09090909 100. ]
"""
arr = np.linspace(1,10,num=10)
print(arr)
arr = np.linspace(1,1,num=10)
print(arr)
"""
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
"""
Numpy切片与索引
ndarray对象的内容可以通过索引或切片来访问和修改与列表的切片操作一样。
ndarray 数组可以基于 0 - n 的下标进行索引,切片对象可以通过内置的 slice 函数,并设置 start, stop 及 step 参数进行,从原数组中切割出一个新数组。
arr = np.linspace(10,20,num=20,dtype=np.uint16)
print(arr)
print()
print(arr[1:])
print(arr[:5])
print(arr[1:5])
print(arr[1:5:1])
print(arr[1:5:2])
print(arr[::2])
print(arr[:3:])
print(arr[:])
print(arr[::])
print(arr[::-1])
"""
[10 10 11 11 12 12 13 13 14 14 15 15 16 16 17 17 18 18 19 20]
[10 11 11 12 12 13 13 14 14 15 15 16 16 17 17 18 18 19 20]
[10 10 11 11 12]
[10 11 11 12]
[10 11 11 12]
[10 11]
[10 11 12 13 14 15 16 17 18 19]
[10 10 11]
[10 10 11 11 12 12 13 13 14 14 15 15 16 16 17 17 18 18 19 20]
[10 10 11 11 12 12 13 13 14 14 15 15 16 16 17 17 18 18 19 20]
[20 19 18 18 17 17 16 16 15 15 14 14 13 13 12 12 11 11 10 10]
"""
arr = np.linspace(10,20,num=20,dtype=np.uint16).reshape(5,4)
print(arr)
print()
print(arr[1:5:2])
"""
[[10 10 11 11]
[12 12 13 13]
[14 14 15 15]
[16 16 17 17]
[18 18 19 20]]
[[12 12 13 13]
[16 16 17 17]]
"""
冒号 : 的解释:如果只放置一个参数,如 [2],将返回与该索引相对应的单个元素。如果为 [2:],表示从该索引开始以后的所有项都将被提取。如果使用了两个参数,如 [2:7],那么则提取两个索引(不包括停止索引)之间的项。
切片还可以包括省略号 …,来使选择元组的长度与数组的维度相同。 如果在行位置使用省略号,它将返回包含行中元素的 ndarray。
import numpy as np
a = np.array([[1,2,3],[3,4,5],[4,5,6]])
print (a[...,1]) # 第2列元素
print (a[1,...]) # 第2行元素
print (a[...,1:]) # 第2列及剩下的所有元素
"""
[2 4 5]
[3 4 5]
[[2 3]
[4 5]
[5 6]]
"""
Numpy高级索引
1、整数数组索引
整数数组索引是使用一个数组(列表)来访问另一个数组的元素。这个数组中的每个元素都是目标数组中某个维度上的索引值。
假如你传入的数组为[2 3 4],[1 2 3],那么你访问到的元素是在数组中(2,1)(3,2)(4,3)位置处的元素
arr = np.arange(20).reshape(5,4)
list = [[1,2,3],[3,2,1]]
print(arr)
print("##########")
print(arr[[1,2,3],[3,2,1]])
row = np.array([[0,0],[arr.shape[0]-1,arr.shape[0]-1]])
col = np.array([[0,arr.shape[1]-1],[0,arr.shape[1]-1]])
print(arr[row,col])
"""
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]
[16 17 18 19]]
##########
[ 7 10 13]
##########
[[ 0 3]
[16 19]]
"""
可以借助切片 : 或 … 与索引数组组合。
a = np.array([[1,2,3], [4,5,6],[7,8,9]])
b = a[1:3, 1:3]
c = a[1:3,[1,2]]
d = a[...,1:]
print(b)
print(c)
print(d)
"""
[[5 6]
[8 9]]
[[5 6]
[8 9]]
[[2 3]
[5 6]
[8 9]]
"""
2、布尔索引
布尔索引也叫逻辑索引
我们可以通过一个布尔数组来索引目标数组。
布尔索引通过布尔运算(如:比较运算符)来获取符合指定条件的元素的数组。
arr = np.arange(20).reshape(5,4)
print(arr[arr>4])
"""
[ 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
"""
#使用 ~(取补运算符)来过滤 NaN。
a = np.array([np.nan, 1,2,np.nan,3,4,5])
print (a[~np.isnan(a)])
"""
[1. 2. 3. 4. 5.]
"""
# 从数组中过滤掉非复数元素。
a = np.array([1, 2+6j, 5, 3.5+5j])
print (a[np.iscomplex(a)])
3、花式索引
花式索引指的是利用整数数组进行索引。
花式索引根据索引数组的值作为目标数组的某个轴的下标来取值。
对于使用一维整型数组作为索引,如果目标是一维数组,那么索引的结果就是对应位置的元素,如果目标是二维数组,那么就是对应下标的行。
花式索引跟切片不一样,它总是将数据复制到新数组中。
4、一维数组
import numpy as np
x = np.arange(9)
print(x)
# 一维数组读取指定下标对应的元素
print("-------读取下标对应的元素-------")
x2 = x[[0, 6]] # 使用花式索引
print(x2)
print(x2[0])
print(x2[1])
5、二维数组
1、传入顺序索引数组
import numpy as np
x=np.arange(32).reshape((8,4))
print(x)# 二维数组读取指定下标对应的行print("-------读取下标对应的行-------")
print (x[[4,2,1,7]])
print (x[[4,2,1,7],[0,3,1,2]])#4,0 2,3 1,1 7,2
2、传入倒序索引数组
import numpy as np
x=np.arange(32).reshape((8,4))
print (x[[-4,-2,-1,-7]])
3、传入多个索引数组(要使用 np.ix_)
np.ix_() 函数就是输入两个数组,产生笛卡尔积的映射关系。
笛卡尔乘积是指在数学中,两个集合 X 和 Y 的笛卡尔积(Cartesian product),又称直积,表示为 X×Y,第一个对象是X的成员而第二个对象是 Y 的所有可能有序对的其中一个成员。
例如 A={a,b}, B={0,1,2},则:
A×B={(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}
B×A={(0, a), (0, b), (1, a), (1, b), (2, a), (2, b)}
import numpy as np
x=np.arange(32).reshape((8,4))
print (x[np.ix_([1,5,7,2],[0,3,1,2])])