Numpy的速度比Python列表的速度快了好几百倍。Numpy数组本身能节省内存。Numpy的另一个强大功能是具有多维数组数据结构,它可以表示向量和矩阵。与Python列表相比,Numpy具有的另一个强大优势是具有大量优化的内置数学函数。这些函数可以非常快速地处理各种复杂的数学计算,并且用到很少代码(无需使用复杂的循环),使程序更容易读懂和理解。注意:在ndarray结构中,里面元素必须是同一类型的,如果不是,会自动的向下转型进行。
import numpy as np
array_diag = np.diag([1, 2, 3, 4]) #生成一个4*4的二维数组,[1,2,3,4]分别在主对角线上
print(array_diag)
# 数组元素个数,结果为16
print(array_diag.size)
print(np.size(array_diag))
# 数组形状,结果为(4, 4)
print(array_diag.shape)
print(np.shape(array_diag))
# 数组维度,结果为2
print(array_diag.ndim)
print(np.ndim(array_diag))
# 数组元素类型
print(array_diag.dtype)
上面代码演示如何对numpy的数组各属性进行访问。
import numpy as np
rand_arr = np.random.rand(2,5,3)
#rand_arr = np.random.random((2,5,3)) #等于上一行代码
randArr = np.random.randint(3,high=100,size=15).reshape(3,5)
print(randArr)
threeDim = np.array([[[11,12,13],[14,15,16],[17,18,19]], [[21,22,23],[24,25,26],[27,28,29]]])
上面的代码用来产生一系列随机数。第1行的代码表示产生一个三维数组,第一个维度上的值2可以理解为2页,第二个维度上的值5可以理解为每页有5行,第三个维度上的值3表示每行上有3个元素。故这个数组总有30个元素。
第4行代表先产生包含15个元素的一维数组,每个元素为[3,100)之间的整数,然后将这个一维数组变成一个3行5列的二维数组。
import numpy as np
a = np.arange(0,100,10) #生成一个起始为0,终点为100(不含),间距为10的序列
print(a)
b = np.linspace(0,100,10)#生成一个首项为0,末项为100(包含)的等差数列;
print(b)
c = np.linspace(0,100,10,endpoint=False) #生成一个首项为0,末项为100(不含)的等差数列,。
print(c)
注意numpy里的arange和python自带的range函数功能相近,起始值都可以比终止值大,也就是都可以产生一系列从大到小的数,但是arange函数的三个参数都可以是小数,而range函数只能是整数。
import numpy as np
arr1 = np.arange(1,10,1).reshape((3,3))
print(arr1)
print(np.median(arr1)) #求中位数
print(np.cumsum(arr1))
print(np.diff(arr1))
rows,cols = np.nonzero(arr1) #获得arr1里所有非零元素的行下标与列下标
arr1 = np.arange(14,2,-1).reshape((3,4))
print(arr1)
print(np.sort(arr1,axis=0)) #arr1里面的每一列从小到大排序
print(np.clip(arr1,3,9)) #clip有修剪的意思,将arr1里的小于3的元素设置为3,大于9的元素设置为9
fl = arr1.flatten() #将二维数组拉平为一维数组
for i in range(len(fl)):
print(fl[i])
上面代码中np.median(arr1)) 针对所有数来求中位数,如果想针对各列分别求中位数,则可以加上axis=0这个参数。np.cumsum(arr1)针对所有数进行累加求和,结果为[ 1 3 6 10 15 21 28 36 45],如果想针对各列分别累加求和,则应当加上axis=0这个参数,结果为:
[[ 1 2 3]
[ 5 7 9]
[12 15 18]]
axis的使用方法,可以参阅我写的博客:。np.diff(arr1)的功能是用后一列的各数减去前一列的各数,当然也可以通过添加axis=0这个参数,达到用后一行的各数减去前一行的各数的效果,结果为:
[[3 3 3]
[3 3 3]]
import numpy as np
arr1 = np.random.randint(1,10,(2,3)) #产生一个[1,10)之间的,2行3列的整形数组
arr2 = np.random.randint(1,10,(2,3))
print(arr1)
print()
print(arr2)
print()
print(np.vstack((arr1,arr2)))#将两个数组垂直(vertical)拼接
print(np.hstack([arr1,arr2]))#将两个数组水平(horizontal)拼接
注意,在使用vstack函数与hstack函数时,应当把要拼接的两个数组用圆括号或者中括号括起来,要拼接的两个数组的数据类型可以不同,比如可用arr1 = np.random.random((2,3))语句来生成一个小数数组,以上拼接语句也可以正常执行的。被拼接的两个数组的大小方面只要求在拼接方向上大小相同即可。
如何产生一个随机的二维整型数组
import numpy as np
#方法一
list1 = [[np.random.randint(10,20) for j in range(1,5)] for i in range(1,4)]
arr1 = np.array(list1)
print(arr1)
#方法二
import numpy as np
list1 = np.random.randint(0,10,(3,4))
print(list1)
以上是产生一个随机的二维整型数组的两种方法,显然第二种方法更简单,但是第一种方法可以做很多扩展。
import numpy as np
A = np.arange(12).reshape((3,4))
print(A)
B,C,D= np.vsplit(A,3) #垂直方向均匀分隔
E,F = np.hsplit(A,2) #水平方向均匀分隔
print(E)
print(F)
要保证在被分割的维度上,对象能够被均匀分割,否则会报错的。
import numpy as np
X = np.array([4,1,14,0,5,2,8])
X_index = X.argsort() #对X进行排序,最后记录的是原数的下标
print(X_index)
x = np.array([0, 1, 1, 3, 2, 1, 7, 2])
bins = np.bincount(x)
print(bins)
bins的值为:[1 3 2 1 0 0 0 1],bincount(x)函数用来统计列表x中各值出现的次数,列表中最小的数与最大的数之间,如果有一些数没有出现过,则出现次数用0代替。因为x里最大值为7,则bins里元素个数为8
import numpy as np
#生成一个首项为10的0次方,末项为10的5次方,共有5个数的等比数列;
a = np.logspace(0,5,5)
print(a)
for i in range(len(a)-1):#因为a是等比数列,故每次循环输出的结果是一样的
print(a[i+1]/a[i])
#生成一个首项为10的0次方,末项为10的4次方,共有5个数的等比数列;
b = np.logspace(0,5,5,endpoint=False)
print(b)
c = np.logspace(0,5,5,base=2,endpoint=False)#生成一个首项为2的0次方,末项为2的4次方,共有5个数的等比数列
print(c)
#生成特殊函数生成数组。
import numpy as np
a=np.array(np.arange(9)).reshape(3,3)
b = np.zeros_like(a) #生成一个形状和类型与a相同,但元素都为0的数组;
print(b)
c = np.ones_like(a) #生成一个形状和类型与a相同,但元素都为1的数组;
print(c)
d = np.empty_like(a) #生成一个形状和类型与a相同,但元素都为空的数组;
print(d)
e = np.full_like(a,np.pi)
print(e)
最后的full_like函数生成一个形状和类型与a相同,元素值都为π的数组,由于a的类型为整数,所以只取整数部分的数值3,如果a是小数数组,如用a=np.random.rand(3,4)这一语句生成,则e也是小数数组。
import numpy as np
A = np.array([1,2,3,4])
B = A #A和B共享同一份内存地址
print(B is A) #True
print(A is B) #True
B[0] = 18 #A和B的第一个数都变成了18
print(A)
print(B)
以上是对象浅拷贝的一个例子
import numpy as np
A = np.array([1,2,3,4])
C = A.copy() #A和C指向的内存地址不相同
print(C is A)# False
print(A is C) # False
C[0] = 18
print(A)
print(C)
以上是对象深拷贝的一个例子,C和A指向的是两个不同的对象,C中的第一个元素值变成了18,A中的第一个元素值并没有改变。
import random
nums = []
for r in range(3):
nums.append([]) #追加的每一个元素又是一个列表
for c in range(3):
n = random.randint(1,100)
nums[r].append(n)
print(nums)
for r in range(len(nums)):
for c in range(len(nums[r])):
i = random.randint(0,len(nums)-1)
j = random.randint(0,len(nums[r])-1)
nums[r][c],nums[i][j] = nums[i][j],nums[r][c]
print(nums)
以上nums是一个列表,输出结果如下
[[7, 83, 93], [28, 98, 99], [5, 53, 41]]
[[5, 93, 99], [98, 53, 28], [41, 7, 83]]
可以用numpy里的二维数组来达到同样的效果,代码如下:
import random
import numpy as np
nums = np.random.randint(1,100,(3,3)) #得到的是一数组
print("原始数组为:\n",nums)
for r in range(len(nums)):
for c in range(len(nums[r])):
i = random.randint(0,len(nums)-1)
j = random.randint(0,len(nums[r])-1)
nums[r][c],nums[i][j] = nums[i][j],nums[r][c]
print("打乱后的数组为:\n",nums)
原始数组为:
[[39 62 30]
[53 53 87]
[88 8 87]]
打乱后的数组为:
[[62 88 30]
[53 8 87]
[39 87 53]]