Numpy科学计算
NumPy介绍
NumPy(Numerical Python)是一个开源的Python科学计算库,用于快速处理任意维度的数组。
NumPy支持常见的数组和矩阵操作。对于同样的数值计算任务,使用Numpy比直接使用Python要简洁的多。
NumPy使用ndarray对象来处理多维数组,该对象是一个快速而灵活的大数据容器。
为什么要学NumPy
1. 快速
2. 方便
3. 科学计算的基础库
2. 方便
3. 科学计算的基础库
NumPy的优势
对于同样的数值计算任务,使用NumPy要比直接编写Python代码便捷得多;
NumPy中的数组的存储效率和输入输出性能均远远优于Python中等价的基本数据结构,且其能够提升的性能 是与数组中的元素成比例的;
NumPy的大部分代码都是用C语言写的,其底层算法在设计时就有着优异的性能,这使得NumPy比纯Python 代码高效得多。
ndarray与Python原生list运算效率对比
import random
import time
import numpy as np
a = []
for i in range(100000000):
a.append(random.random())
t1 = time.time()
sum1=sum(a)
t2=time.time()
b=np.array(a)
t4=time.time()
sum3=np.sum(b)
t5=time.time()
print(t2-t1, t5-t4)
输出:
8.297281980514526 1.7647507190704346
t2-t1为使用python自带的求和函数消耗的时间,t5-t4为使用numpy求和消耗的时间,结论为: ndarray的计算速度要快很多,更高效。
创建一维数组
import numpy as np list1 = [1,2,3,4] oneArray = np.array(list1) print(type(oneArray)) print(oneArray) 输出: <class 'numpy.ndarray'> [1 2 3 4]
import numpy as np
# 创建数组的多种形式
# 1. 直接传入列表的方式
t1 = np.array([1,2,3])
print(t1)
print(type(t1))
# 2. 传入range生成序列
t2 = np.array(range(10))
print(t2)
print(type(t2))
# 3. 使用numpy自带的np.arange()生成数组
t3 = np.arange(0,10,2)
print(t3)
print(type(t3))
输出:
[1 2 3]
<class 'numpy.ndarray'>
[0 1 2 3 4 5 6 7 8 9]
<class 'numpy.ndarray'>
[0 2 4 6 8]
<class 'numpy.ndarray'>
创建二位数组
import numpy as np
list2 = [[1,2],[3,4],[5,6]]
twoArray = np.array(list2)
print(twoArray)
#返回数组类型
print(twoArray.ndim)
#返回数组形状
print(twoArray.shape)
#返回数组的元素个数
print(twoArray.size)
输出:
[[1 2]
[3 4]
[5 6]]
2
(3, 2)
6
调整数组形状
#二维变三维
import numpy as np
four = np.array([[1,2,3],[4,5,6]])
# 修改的是原有的
four.shape = (3,2)
print(four)
print("-"*20)
# 返回一个新的数组
five = four.reshape(3,2)
print(five)
输出:
[[1 2]
[3 4]
[5 6]]
--------------------
[[1 2]
[3 4]
[5 6]]
#多维变一维
import numpy as np
four = np.array([[1,2,3],[4,5,6]])
# 将多维变成一维数组
five = four.reshape((6,),order='F')
# 默认情况下‘C’以行为主的顺序展开,‘F’(Fortran风格)意味着以列的顺序展开
six = four.flatten(order='F')
print(five)
print(six)
输出:
[1 4 2 5 3 6]
[1 4 2 5 3 6]
数组转换为list
import numpy as np a= np.array([9, 12, 88, 14, 25]) list_a = a.tolist() print(list_a) print(type(list_a)) 输出: [9, 12, 88, 14, 25] <class 'list'>
NumPy的数据类型
import numpy as np
import random
f = np.array([1,2,3,4,5], dtype = np.int16)
# 返回数组中每个元素的字节单位长度
print(f.itemsize)
# 获取数据类型
print(f.dtype)
# 调整数据类型
f1 = f.astype(np.int64)
print(f1.dtype)
# 拓展随机生成小数
# 使用python语法,保留两位
print(round(random.random(),2))
arr = np.array([random.random() for i in range(10)]) # 取小数点后两位
print(np.round(arr,2))
输出:
2
int16
int64
0.02
[0.72 0.02 0.93 0.99 0.12 0.16 0.19 0.25 0.89 0. ]
数组的计算
import numpy as np
import random
t1 = np.arange(24).reshape((6,4))
print(t1)
print("-"*20)
print(t1+2)
print("-"*20)
print(t1*2)
print("-"*20)
print(t1/2)
输出:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]
--------------------
[[ 2 3 4 5]
[ 6 7 8 9]
[10 11 12 13]
[14 15 16 17]
[18 19 20 21]
[22 23 24 25]]
--------------------
[[ 0 2 4 6]
[ 8 10 12 14]
[16 18 20 22]
[24 26 28 30]
[32 34 36 38]
[40 42 44 46]]
--------------------
[[ 0. 0.5 1. 1.5]
[ 2. 2.5 3. 3.5]
[ 4. 4.5 5. 5.5]
[ 6. 6.5 7. 7.5]
[ 8. 8.5 9. 9.5]
[10. 10.5 11. 11.5]]
#同种形状的数组(对应位置进行计算操作)
import numpy as np
import random
t1 = np.arange(24).reshape((6,4))
t2 = np.arange(100,124).reshape((6,4))
print(t1+t2)
print("-"*20)
print(t1*t2)
输出:
[[100 102 104 106]
[108 110 112 114]
[116 118 120 122]
[124 126 128 130]
[132 134 136 138]
[140 142 144 146]]
--------------------
[[ 0 101 204 309]
[ 416 525 636 749]
[ 864 981 1100 1221]
[1344 1469 1596 1725]
[1856 1989 2124 2261]
[2400 2541 2684 2829]]
import numpy as np
import random
t1 = np.arange(24).reshape((4,6))
t2 = np.arange(0,6)
print(t1)
print("-"*20)
print(t2)
print("-"*20)
print(t1-t2)
输出:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
--------------------
[0 1 2 3 4 5]
--------------------
[[ 0 0 0 0 0 0]
[ 6 6 6 6 6 6]
[12 12 12 12 12 12]
[18 18 18 18 18 18]]
#列形状相同(会与每一个相同维度的数组的对应位相操作)
import numpy as np
import random
t1 = np.arange(24).reshape((4, 6))
t2 = np.arange(4).reshape((4, 1))
print(t1)
print("-"*20)
print(t2)
print("-"*20)
print(t1-t2)
输出:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
--------------------
[[0]
[1]
[2]
[3]]
--------------------
[[ 0 1 2 3 4 5]
[ 5 6 7 8 9 10]
[10 11 12 13 14 15]
[15 16 17 18 19 20]]
数组中轴的计算
import numpy as np
a = np.array([[1,2,3],[4,5,6]])
print(np.sum(a,axis=0)) #0轴
print(np.sum(a,axis = 1)) #1轴
输出:
[5 7 9]
[ 6 15]
import numpy as np
a = np.arange(27).reshape((3,3,3))
b = np.sum(a, axis=0)
print(a)
print("-"*20)
print(b)
输出:
[[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]]
[[ 9 10 11]
[12 13 14]
[15 16 17]]
[[18 19 20]
[21 22 23]
[24 25 26]]]
--------------------
[[27 30 33]
[36 39 42]
[45 48 51]]
数组的索引和切片
#一维数组的操作方法
import numpy as np
a = np.arange(10)
# 冒号分隔切片参数 start:stop:step 来进行切片操作
print(a[2:7:2])# 从索引 2 开始到索引 7 停止,间隔为 2
# 如果只放置一个参数,如 [2],将返回与该索引相对应的单个元素
print(a[2],a)
# 如果为 [2:],表示从该索引开始以后的所有项都将被提取
print(a[2:])
输出:
[2 4 6]
2 [0 1 2 3 4 5 6 7 8 9]
[2 3 4 5 6 7 8 9]
#多维数组的操作方法
import numpy as np
t1 = np.arange(24).reshape(4,6)
print(t1)
print('-'*20)
print(t1[1]) # 取一行(一行代表是一条数据,索引也是从0开始的)
print(t1[1,:]) # 取一行
输出:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
--------------------
[ 6 7 8 9 10 11]
[ 6 7 8 9 10 11]
print(t1[1:])# 取连续的多行 print(t1[1:3,:])# 取连续的多行
输出:
[[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
print(t1[[0,2,3]])# 取不连续的多行 print(t1[[0,2,3],:])# 取不连续的多行
输出:
[[ 0 1 2 3 4 5]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
print(t1[:,1])# 取一列
输出:
[ 1 7 13 19]
print(t1[:,1:])# 连续的多列
输出:
[[ 1 2 3 4 5]
[ 7 8 9 10 11]
[13 14 15 16 17]
[19 20 21 22 23]]
print(t1[:,[0,2,3]])# 取不连续的多列
输出:
[[ 0 2 3]
[ 6 8 9]
[12 14 15]
[18 20 21]]
print(t1[2,3])# # 取某一个值,三行四列
输出:
15
print(t1[[0,1,1]])
print('-'*20)
print(t1[[0,1,1],[0,1,3]])# 取多个不连续的值,[[行,行。。。],[列,列。。。]]
输出:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[ 6 7 8 9 10 11]]
--------------------
[0 7 9]
数组中数值修改
import numpy as np t = np.arange(24).reshape(4,6) # 修改某一行的值 t[1,:]=0 (t) # 修改某一列的值 t[:,1]=0 # 修改连续多行 t[1:3,:]=0 # 修改多行多列,取第二行到第四行,第三列到第五列 t[1:4,2:5]=0 # 修改多个不相邻的点 t[[0,1],[0,3]]=0 # 可以根据条件修改,比如讲小于10的值改掉 t[t<10]=0 # 使用逻辑判断 # np.logical_and & # np.logical_or | # np.logical_not ~ t[(t>2)&(t<6)]=0 t[(t<2)|(t>6)]=0 t[~(t>6)]=0 # 拓展 # 三目运算( np.where(condition, x, y)满足条件(condition),输出x,不满足输出y。)) score = np.array([[80,88],[82,81],[75,81]]) result = np.where(score>80,True,False) print(result)
数组的添加、删除和去重
添加
#append方法
'''
参数说明:
参数说明:
arr:输入数组
values:要向arr添加的值,需要和arr形状相同(除了要添加的轴)
axis:默认为 None。当axis无定义时,是横向加成,返回总是为一维数组!当axis有定义的时候,分别为0和1的时候。当
axis有定义的时候,分别为0和1的时候(列数要相同)。当axis为1时,数组是加在右边(行数要相同)。
'''
import numpy as np
a = np.array([[1,2,3],[4,5,6]])
print ('第一个数组:')
print (a)
print ('\n')
print ('向数组添加元素:')
print (np.append(a, [7,8,9]))
print ('\n')
print ('沿轴 0 添加元素:')
print (np.append(a, [[7,8,9]],axis = 0))
print ('\n')
print ('沿轴 1 添加元素:')
print (np.append(a, [[5,5,5],[7,8,9]],axis = 1))
输出:
第一个数组:
[[1 2 3]
[4 5 6]]
向数组添加元素:
[1 2 3 4 5 6 7 8 9]
沿轴 0 添加元素:
[[1 2 3]
[4 5 6]
[7 8 9]]
沿轴 1 添加元素:
[[1 2 3 5 5 5]
[4 5 6 7 8 9]]
#insert方法
import numpy as np
a = np.array([[1,2],[3,4],[5,6]])
print ('第一个数组:')
print (a)
print ('\n')
print ('未传递 Axis 参数。 在插入之前输入数组会被展开。')
print (np.insert(a,3,[11,12]))
print ('\n')
print ('传递了 Axis 参数。 会广播值数组来配输入数组。')
print ('沿轴 0 广播:')
print (np.insert(a,1,[11],axis = 0))
print ('\n')
print ('沿轴 1 广播:')
print (np.insert(a,1,11,axis = 1))
输出:
第一个数组:
[[1 2]
[3 4]
[5 6]]
未传递 Axis 参数。 在插入之前输入数组会被展开。
[ 1 2 3 11 12 4 5 6]
传递了 Axis 参数。 会广播值数组来配输入数组。
沿轴 0 广播:
[[ 1 2]
[11 11]
[ 3 4]
[ 5 6]]
沿轴 1 广播:
[[ 1 11 2]
[ 3 11 4]
[ 5 11 6]]
删除
import numpy as np
a = np.arange(12).reshape(3,4)
print ('第一个数组:')
print (a)
print ('\n')
print ('未传递 Axis 参数。 在删除之前输入数组会被展开。')
print (np.delete(a,5))
print ('\n')
print ('删除每一行中的第二列:')
print (np.delete(a,1,axis = 1))
print ('\n')
输出:
第一个数组:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
未传递 Axis 参数。 在删除之前输入数组会被展开。
[ 0 1 2 3 4 6 7 8 9 10 11]
删除每一行中的第二列:
[[ 0 2 3]
[ 4 6 7]
[ 8 10 11]]
去重
# numpy.unique 函数用于去除数组中的重复元素。
'''
arr:输入数组,如果不是一维数组则会展开 return_index:如果为true,返回新列表元素在旧列表中的位置(下标),并以列表形式储 return_inverse:如果为true,返回旧列表元素在新列表中的位置(下标),并以列表形式储 return_counts:如果为true,返回去重数组中的元素在原数组中的出现次数
'''
import numpy as np
a = np.array([5,2,6,2,7,5,6,8,2,9])
print ('第一个数组:')
print (a)
print ('\n')
print ('第一个数组的去重值:')
u = np.unique(a)
print (u)
print ('\n')
print ('去重数组的索引数组:')
u,indices = np.unique(a, return_index = True)
print (indices)
print ('\n')
print ('我们可以看到每个和原数组下标对应的数值:')
print (a)
print ('\n')
print ('去重数组的下标:')
u,indices = np.unique(a,return_inverse = True)
print (u)
print (indices)
print ('\n')
print ('返回去重元素的重复数量:')
u,indices = np.unique(a,return_counts = True)
print (u)
print (indices)
输出:
第一个数组:
[5 2 6 2 7 5 6 8 2 9]
第一个数组的去重值:
[2 5 6 7 8 9]
去重数组的索引数组:
[1 0 2 4 7 9]
我们可以看到每个和原数组下标对应的数值:
[5 2 6 2 7 5 6 8 2 9]
去重数组的下标:
[2 5 6 7 8 9]
[1 0 2 0 3 1 2 4 0 5]
返回去重元素的重复数量:
[2 5 6 7 8 9]
[3 2 2 1 1 1]
numpy的计算
import numpy as np
score = np.array([[80,88],[82,81],[75,81]])
# 1. 获取所有数据最大值
result = np.max(score)
# 2. 获取某一个轴上的数据最大值
result = np.max(score,axis=0)
# 3. 获取最小值
result = np.min(score)
# 4. 获取某一个轴上的数据最小值
result = np.min(score,axis=0)
# 5. 数据的比较
result = np.maximum([-2, -1, 0, 1, 2], 0) # 第一个参数中的每一个数与第二个参数比较返回大的
result = np.minimum([-2, -1, 0, 1, 2], 0) # 第一个参数中的每一个数与第二个参数比较返回小的
result = np.maximum([-2, -1, 0, 1, 2], [1,2,3,4,5]) # 接受的两个参数,也可以大小一致;第二个参数只是一个单独的值时,其实是用到了维度的广播机制;
# 6. 求平均值
result = np.mean(score) # 获取所有数据的平均值
result = np.mean(score,axis=0) # 获取某一行或者某一列的平均值
# 7. 返回给定axis上的累计和
arr = np.array([[1,2,3], [4,5,6]])
print(arr)
print(arr.cumsum(0))
# 8. argmin求最小值索引
result = np.argmin(score,axis=0)
# 9. 求每一列的标准差
# 标准差是一组数据平均值分散程度的一种度量。一个较大的标准差,代表大部分数值和其平均值之间差异较大; # 一个较小的标准差,代表这些数据较接近平均值反应出数据的波动稳定情况,越大表示波动越大,越不稳定。
result = np.std(score,axis=0)
#10. 极值
result=np.ptp(score,axis=None)#就是最大值和最小值的差
通用函数
数组的拼接
import numpy as np
# 1. 根据轴连接的数组序列
a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,8]])
# 要求a,b两个数组的维度相同
print ('沿轴 0 连接两个数组:')
print (np.concatenate((a,b),axis= 0))
print ('\n')
print ('沿轴 1 连接两个数组:')
print (np.concatenate((a,b),axis = 1))
# 2. 根据轴进行堆叠
print ('沿轴 0 连接两个数组:')
print (np.stack((a,b),axis= 0))
print ('\n')
print ('沿轴 1 连接两个数组:')
print (np.stack((a,b),axis = 1))
# 3. 矩阵垂直拼接
v1 = [[0,1,2,3,4,5],
[6,7,8,9,10,11]]
v2 = [[12,13,14,15,16,17],
[18,19,20,21,22,23]]
result = np.vstack((v1,v2))
print(result)
# 4. 矩阵水平拼接
v1 = [[0,1,2,3,4,5],
[6,7,8,9,10,11]]
v2 = [[12,13,14,15,16,17],
[18,19,20,21,22,23]]
result = np.hstack((v1,v2))
print(result)
输出:
沿轴 0 连接两个数组:
[[1 2]
[3 4]
[5 6]
[7 8]]
沿轴 1 连接两个数组:
[[1 2 5 6]
[3 4 7 8]]
沿轴 0 连接两个数组:
[[[1 2]
[3 4]]
[[5 6]
[7 8]]]
沿轴 1 连接两个数组:
[[[1 2]
[5 6]]
[[3 4]
[7 8]]]
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
[[ 0 1 2 3 4 5 12 13 14 15 16 17]
[ 6 7 8 9 10 11 18 19 20 21 22 23]]
数组的分割
import numpy as np
# 1. 将一个数组分割为多个子数组
'''
参数说明:
ary:被分割的数组 indices_or_sections:果是一个整数,就用该数平均切分,如果是一个数组,为沿轴切分的位置(左开右闭) axis:沿着哪个维度进行切向,默认为0,横向切分。为1时,纵向切分
'''
arr = np.arange(9).reshape(3,3)
print ('将数组分为三个大小相等的子数组:')
b = np.split(arr,3)
print (b)
#2.numpy.hsplit 函数用于水平分割数组,通过指定要返回的相同形状的数组数量来拆分原数组。 # floor() 返回数字的下舍整数。 col方向
harr = np.floor(10 * np.random.random((2, 6)))
print ('原array:')
print(harr)
print ('拆分后:')
print(np.hsplit(harr, 3))
# 3.numpy.vsplit 沿着垂直轴分割 row方向
a = np.arange(16).reshape(4,4)
print ('第一个数组:')
print (a)
print ('\n')
print ('竖直分割:')
b = np.vsplit(a,2)
print (b)
输出:
将数组分为三个大小相等的子数组:
[array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]
原array:
[[1. 4. 9. 3. 7. 2.]
[3. 4. 3. 1. 6. 3.]]
拆分后:
[array([[1., 4.],
[3., 4.]]), array([[9., 3.],
[3., 1.]]), array([[7., 2.],
[6., 3.]])]
第一个数组:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]]
竖直分割:
[array([[0, 1, 2, 3],
[4, 5, 6, 7]]), array([[ 8, 9, 10, 11],
[12, 13, 14, 15]])]
数组中的nan和inf
import numpy as np # 创建一个nan和inf a = np.nan b = np.inf print(a,type(a)) print(b,type(b)) # --判断数组中为nan的个数(注意:float类型的数据才能赋值nan) t = np.arange(24,dtype=float).reshape(4,6) # 可以使用np.count_nonzero() 来判断非零的个数 print(np.count_nonzero(t)) # 将三行四列的数改成nan t[3,4] = np.nan # 并且 np.nan != np.nan 结果 是TRUE # 所以我们可以使用这两个结合使用判断nan的个数 print(np.count_nonzero(t != t)) # 注意: nan和任何数计算都为nan print(np.sum(t,axis=0)) # 将nan替换为0 t[np.isnan(t)] = 0 print(t) #----------练习: 处理数组中nan t = np.arange(24).reshape(4,6).astype('float') # 将数组中的一部分替换nan t[1,3:] = np.nan print(t) 输出: nan <class 'float'> inf <class 'float'> 23 1 [36. 40. 44. 48. nan 56.] [[ 0. 1. 2. 3. 4. 5.] [ 6. 7. 8. 9. 10. 11.] [12. 13. 14. 15. 16. 17.] [18. 19. 20. 21. 0. 23.]] [[ 0. 1. 2. 3. 4. 5.] [ 6. 7. 8. nan nan nan] [12. 13. 14. 15. 16. 17.] [18. 19. 20. 21. 22. 23.]]
二维数组的转换
import numpy as np
#对换数组的维度
a = np.arange(12).reshape(3,4)
print ('原数组:')
print (a )
print ('\n')
print ('对换数组:')
print (np.transpose(a))
# 与transpose一致
a = np.arange(12).reshape(3,4)
print ('原数组:')
print (a)
print ('\n')
print ('转置数组:')
print (a.T)
# 函数用于交换数组的两个轴
t1 = np.arange(24).reshape(4,6)
re = t1.swapaxes(1,0)
print ('原数组:')
print (t1)
print ('\n')
print ('调用 swapaxes 函数后的数组:')
print (re)
输出:
原数组:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
对换数组:
[[ 0 4 8]
[ 1 5 9]
[ 2 6 10]
[ 3 7 11]]
原数组:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
转置数组:
[[ 0 4 8]
[ 1 5 9]
[ 2 6 10]
[ 3 7 11]]
原数组:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
调用 swapaxes 函数后的数组:
[[ 0 6 12 18]
[ 1 7 13 19]
[ 2 8 14 20]
[ 3 9 15 21]
[ 4 10 16 22]
[ 5 11 17 23]]
赠人玫瑰,手有余香,如果我的文章有幸能够帮到你,麻烦帮忙点下右下角的推荐,谢谢!
作者: imcati
出处: https://www.cnblogs.com/imcati/>
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出, 原文链接