Numpy是高性能科学计算和数据分析的基础包。它是pandas等其他各种工具的基础。
NumPy的主要功能:
ndarray,一个多维数组结构,高效且节省空间 无需循环对整组数据进行快速运算的数学函数 *读写磁盘数据的工具以及用于操作内存映射文件的工具 *线性代数、随机数生成和傅里叶变换功能 *用于集成C、C++等代码的工具
- 安装方法:pip install numpy
- 引用方式:import numpy as np
------> 以下测试都是在ipython中 <------
初识
import numpy as np
a=np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) '_'代表的是上方的结果 "__"代表的是上上方的结果 for i in a:
print(i,end=',') 0,1,2,3,4,5,6,7,8,9, b=list(range(10))
b [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] import sys
sys.getsizeof(b) 200 a=np.array(range(10))
sys.getsizeof(a) 136 可以看出,原生的列表占用内存更大,而ndarray类型占用的小是因为numpy内部使用c++实现的
常用计算
#计算购物车里的商品的总和,有单价和商品数量 import random
#单价
prize=[round(random.uniform(10.0,20.0),2) for i in range(10)]
prize [16.56, 19.02, 12.33, 13.62, 14.85, 18.77, 15.65, 17.68, 13.01, 11.61] #数量
num=[round(random.uniform(1,10)) for i in range(10)]
num [4, 9, 4, 3, 6, 1, 6, 9, 9, 2] #两个列表里的商品和数量是对应的,现在求和 #传统的方式,写个循环 def ceshi(a,b):
sum=0
for i,j in zip(prize,num):
sum+=i*j
return sum print(ceshi(prize,num)) 828.8000000000001 import timeit
%timeit ceshi(prize,num) 2.1 µs ± 193 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) 大概用时2-3微秒 import numpy as np
# 使用ndarray计算 #先转换成ndarray
prize_np=np.array(prize)
prize_np array([ 16.56, 19.02, 12.33, 13.62, 14.85, 18.77, 15.65, 17.68,13.01, 11.61]) num_np=np.array(num)
num_np array([4, 9, 4, 3, 6, 1, 6, 9, 9, 2]) #点乘
np.dot(prize_np,num_np) 828.80000000000007 #看时间上的消耗
%timeit np.dot(prize_np,num_np) 1.07 µs ± 20 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) 如果数据量大的话,ndarray在时间上的优势会更明显
上边的写法还有很多 prize_np*num_np array([ 66.24, 171.18, 49.32, 40.86, 89.1 , 18.77, 93.9 ,
159.12, 117.09, 23.22]) #相乘,就是对应位置上的数据做乘法 _.sum() #再进行求和操作 828.80000000000007 prize_np*2 array([ 33.12, 38.04, 24.66, 27.24, 29.7 , 37.54, 31.3 , 35.36,26.02, 23.22]) prize_np+100 array([ 116.56, 119.02, 112.33, 113.62, 114.85, 118.77, 115.65,117.68, 113.01, 111.61]) prize_np/2 array([ 8.28 , 9.51 , 6.165, 6.81 , 7.425, 9.385, 7.825, 8.84 ,6.505, 5.805]) prize_np**2 array([ 274.2336, 361.7604, 152.0289, 185.5044, 220.5225, 352.3129,244.9225, 312.5824, 169.2601, 134.7921]) #取商
prize_np//2 array([ 8., 9., 6., 6., 7., 9., 7., 8., 6., 5.]) #取实际的除法元算结果
prize_np/2 array([ 8.28 , 9.51 , 6.165, 6.81 , 7.425, 9.385, 7.825, 8.84 ,6.505, 5.805]) prize_np**prize_np array([ 1.54041985e+20, 2.14083871e+24, 2.82862082e+13,2.80215533e+15, 2.51268378e+17, 7.99695030e+23,4.94480820e+18, 1.13628263e+22, 3.13868425e+14,2.30516529e+12]) ndarray 数组里的类型必须一致,一般大多数时候存储的是科学计算类型(整数和小数),字符串放里边其实也不快,不如用列表
数据类型
dtype
bool_,
int(8,16,32,64),
uint(8,16,32,64),
float(16,32,64)
#查看数据类型
prize_np.dtype dtype('float64') 看出这是一个64位(4字节)的浮点类型 a=np.arange(100)
a array([ 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, 28, 29, 30, 31, 32, 33,34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]) a.dtype dtype('int32') 说明该类型是32位的int类型 # 获取长度 a.size 100 #取数组的纬度,返回的是元组,多维数组就可以看到效果
a.shape (100,) b=np.array([[5,4,23],[1,6,23]])
b array([[ 5, 4, 23],[ 1, 6, 23]]) b.shape (2, 3) 两行三列 # 返回维度值
a.ndim 1 b.ndim 2 # 数组的转置(倒置),将行变列,列变行
b.T array([[ 5, 1],[ 4, 6],[23, 23]])
类型转换:astype()
转换数据类型,nbarray本身只能存储一种数据类型,压迫转换的,需要astype # 将b里的数转换为小数
b[0][0]=3.2
b array([[ 3, 4, 23],[ 1, 6, 23]]) # 转换之后,会自动取为整数,不是我们要的效果 #通过修改数据类型
b.dtype="float32"
b.dtype dtype('float32') b array([[ 4.20389539e-45, 5.60519386e-45, 3.22298647e-44],[ 1.40129846e-45, 8.40779079e-45, 3.22298647e-44]], dtype=float32) # 虽然类型修改成功,但是植发生了变化,因为在计算机里存储的二进制形式整数和小数是不一样的,这么暴力的转换是不行的 b.dtype='int32'
b array([[ 3, 4, 23],[ 1, 6, 23]]) # 用astype,记住这里是有返回值的,并没有改变原有的数据
c=b.astype("float32")
c array([[ 3., 4., 23.],[ 1., 6., 23.]], dtype=float32) c[0][0]=3.2
c array([[ 3.20000005, 4. , 23. ],
[ 1. , 6. , 23. ]], dtype=float32) # 可以看出转换成功(3.20000005,这里是32位的精度的问题,如果改为float64,精度就非常高,就没有0000005)
c=b.astype("float64")
c array([[ 3., 4., 23.],[ 1., 6., 23.]]) c[0][0]=3.2
c array([[ 3.2, 4. , 23. ],[ 1. , 6. , 23. ]]) 将列表转换为数组,可选择显式指定dtype # 列表类型转ndarray a=list(range(10)) a=np.array(a,dtype="float")
#会自动匹配float32或者64位
a array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.]) a.dtype dtype('float64')
创建ndarray
arange:range的numpy版,支持浮点数
np.arange(10,100) array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,95, 96, 97, 98, 99]) ## 步长
np.arange(10,100,20) array([10, 30, 50, 70, 90]) # 强大的小数步长(普通的range是不支持的)
np.arange(10,100,23.56) array([ 10. , 33.56, 57.12, 80.68])
linspace:类似arange(),第三个参数为数组长度
# 将3到10的数平均分为11份
np.linspace(3,10,11) array([ 3. , 3.7, 4.4, 5.1, 5.8, 6.5, 7.2, 7.9, 8.6,
9.3, 10. ])
zeros() 根据指定形状和dtype创建全0数组
np.zeros(10) array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]) np.zeros(10,dtype="int") array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) # d多维的
np.zeros((3,5)) array([[ 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0.]])
ones() 根据指定形状和dtype创建全1数组
np.ones(10) array([ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]) np.ones(10,dtype="float") array([ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]) np.ones((5,8)) array([[ 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1.]]) np.ones((2,3,5)) array([[[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.]], [[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.]]])
empty() 根据指定形状和dtype创建空数组(随机值)
np.empty(10) array([ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]) np.empty(6) array([ 3.2, 4. , 23. , 1. , 6. , 23. ]) np.empty((3,2)) array([[ 3.2, 4. ],[ 23. , 1. ],[ 6. , 23. ]])
ones和zeros 是先开一块空间,然后再去填充数据
empty是开一块空间,但是不去赋值,而里边的数据是内存里边没用的数据(已经被释放的数据),所以empty更省时间
reshape 重新调整矩阵的行数、列数、维数
a=np.arange(15)
a array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]) a.reshape((3,5)) array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]]) #相乘必须是15
a.reshape((3,4))
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-83-a5f367ac0d99> in <module>()
----> 1 a.reshape((3,4)) ValueError: cannot reshape array of size 15 into shape (3,4) #生成多维数组
a=np.arange(15).reshape(3,5)
a array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
eye() 根据指定边长和dtype创建单位矩阵
#对角的值都相等
np.eye(5) array([[ 1., 0., 0., 0., 0.],
[ 0., 1., 0., 0., 0.],
[ 0., 0., 1., 0., 0.],
[ 0., 0., 0., 1., 0.],
[ 0., 0., 0., 0., 1.]])
索引和切片
一维切片
b=np.arange(10,40,3)
b array([10, 13, 16, 19, 22, 25, 28, 31, 34, 37]) b[0] 10 b[7] 31 b[:-1] array([10, 13, 16, 19, 22, 25, 28, 31, 34]) b[:] array([10, 13, 16, 19, 22, 25, 28, 31, 34, 37])
二维切片
a=np.array([list(range(10)),[5,4,2,9,7,6,1,8,3,0]])
a array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[5, 4, 2, 9, 7, 6, 1, 8, 3, 0]]) a[1][9]
0 a[1][4]
7 a[1,2]
2 # 如果我们得到第一行下的第二列到第4列的数据
a[0][1:5]
array([1, 2, 3, 4]) # 再比如要切的数据是[行切,列切]
# [2,3,4]
# [2,9,7] a[0:2,2:5]
array([[2, 3, 4],
[2, 9, 7]])
copy
与列表不同,数组切片时并不会自动复制,在切片数组上的修改会影响原数组。 b
array([10, 13, 16, 19, 22, 25, 28, 31, 34, 37]) c=b[0:4]
c
array([10, 13, 16, 19]) #修改切片后的数据
c[0]=12323
c
array([12323, 13, 16, 19]) #修改切片后的数据,原数据b也跟着发生了变化,也就是说,切片并不会复制一份数据 b
array([12323, 13, 16, 19, 22, 25, 28, 31, 34]) # 可以使用copy的方式复制一份数据
c=b[:4].copy()
c[0]=8888888
c
array([8888888, 13, 16, 19]) b
array([12323, 13, 16, 19, 22, 25, 28, 31, 34])
布尔值索引
a=np.array([round(random.uniform(1,10)) for i in range(10)])
a
array([5, 5, 2, 3, 7, 8, 4, 1, 7, 4]) # 求大于5的数
a[a>5]
array([7, 8, 7]) #a>5会对a中的每一个元素进行判断,返回一个布尔数组 布尔型索引:
# 将同样大小的布尔数组传进索引,会返回一个由所有True对应位置的元素的数组
a>5
array([False, False, False, False, True, True, False, False, True, False], dtype=bool) #这里一定是拿到的是bool为true的数值
a[a>5]
array([7, 8, 7]) #取反
a[~(a>5)]
array([5, 5, 2, 3, 4, 1, 4])
# 给一个数组,选出数组中所有大于5的偶数, #请记得一定要加括号括起来
(a>5) & (a%2==0)
array([False, False, False, False, False, True, False, False, False, False], dtype=bool) a[(a>5) & (a%2==0)]
array([8]) a[(a>5) | (a%2==0)]
array([2, 7, 8, 4, 7, 4]) 7 & 5
5 7 | 5
7 True | False
True
花式索引
a=np.array([10, 13, 16, 19, 22, 25, 28, 31, 34, 37])
a
array([10, 13, 16, 19, 22, 25, 28, 31, 34, 37]) #对于一个数组,选出其第1,3,4,6,7个元素
#里边必须传一个列表
a[[1,3,4,6,7]]
array([13, 19, 22, 28, 31]) #对一个二维数组,选出其第一列和第三列,组成新的二维数组。
b=np.arange(15).reshape(3,5)
b
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]]) b[:,[0,2]]
array([[ 0, 2],
[ 5, 7],
[10, 12]]) # 选出其第一列和第三列,(True和False必须写满,有多少列就得写多少True和False)
b[:,[True,False,True,False,False]]
array([[ 0, 2],
[ 5, 7],
[10, 12]])
通用函数
一元函数(参数只有一个数组)
- abs
- sqrt
- exp
- log
- ceil
- floor
- rint
- trunc
- modf
- isnan
- isinf
- cos
- sin
- tan
a=np.arange(0,5,0.2)
a
array([ 0. , 0.2, 0.4, 0.6, 0.8, 1. , 1.2, 1.4, 1.6, 1.8, 2. ,
2.2, 2.4, 2.6, 2.8, 3. , 3.2, 3.4, 3.6, 3.8, 4. , 4.2,
4.4, 4.6, 4.8]) # 让 所有的数字四舍五入 round
np.round(a)
array([ 0., 0., 0., 1., 1., 1., 1., 1., 2., 2., 2., 2., 2.,
3., 3., 3., 3., 3., 4., 4., 4., 4., 4., 5., 5.]) # 让 四舍五入,去掉小数+1(math.ceil)
np.ceil(3.2)
4.0 # 让 四舍五入,-1(math.floor)
np.floor(31.6)
31.0 #round效果一样
np.rint(a)
array([ 0., 0., 0., 1., 1., 1., 1., 1., 2., 2., 2., 2., 2.,
3., 3., 3., 3., 3., 4., 4., 4., 4., 4., 5., 5.]) #trunc,向0取整,找靠近0的整数(math.trunc)
np.trunc(-8.1)
-8.0 #trunc,向0取整,找靠近0的整数(math.trunc)
np.trunc(8.1)
8.0 # 取小数和整数部分
a
array([ 0. , 0.2, 0.4, 0.6, 0.8, 1. , 1.2, 1.4, 1.6, 1.8, 2. ,
2.2, 2.4, 2.6, 2.8, 3. , 3.2, 3.4, 3.6, 3.8, 4. , 4.2,
4.4, 4.6, 4.8])
np.modf(a)
(array([ 0. , 0.2, 0.4, 0.6, 0.8, 0. , 0.2, 0.4, 0.6, 0.8, 0. ,
0.2, 0.4, 0.6, 0.8, 0. , 0.2, 0.4, 0.6, 0.8, 0. , 0.2,
0.4, 0.6, 0.8]),
array([ 0., 0., 0., 0., 0., 1., 1., 1., 1., 1., 2., 2., 2.,
2., 2., 3., 3., 3., 3., 3., 4., 4., 4., 4., 4.]))
x,y=np.modf(a) #整数部分
x
array([ 0. , 0.2, 0.4, 0.6, 0.8, 0. , 0.2, 0.4, 0.6, 0.8, 0. ,
0.2, 0.4, 0.6, 0.8, 0. , 0.2, 0.4, 0.6, 0.8, 0. , 0.2,
0.4, 0.6, 0.8]) #小数部分
y
array([ 0., 0., 0., 0., 0., 1., 1., 1., 1., 1., 2., 2., 2.,
2., 2., 3., 3., 3., 3., 3., 4., 4., 4., 4., 4.])
inf和NaN
# 我们知道,在除法的世界里,有除数不能为0的规则
5/0
--------------------------------------------------------------------------- ZeroDivisionError Traceback (most recent call last) <ipython-input-247-e08a7e02982d> in <module>()
1 # 我们知道,在除法的世界里,有除数不能为0的规则
----> 2 5/0 ZeroDivisionError: division by zero
a=np.array([12,3,4,5,6])
a
array([12, 3, 4, 5, 6]) b=np.array([12,3,4,5,0])
b
array([12, 3, 4, 5, 0]) a/b
d:\program files (x86)\python35\lib\site-packages\ipykernel_launcher.py:1: RuntimeWarning: divide by zero encountered in true_divide
"""Entry point for launching an IPython kernel. array([ 1., 1., 1., 1., inf])
# 并没有报错,inf这里代表的是无限大的意思,比如除数越小,结果越大,当等于0的时候,就是无限大(微积分的世界)
8/0.00000000001
800000000000.0
c=np.array([12,3,4,5,0])
c
array([12, 3, 4, 5, 0])
d=np.array([123,3,4,0,0])
d
array([123, 3, 4, 0, 0])
f=c/d
f
d:\program files (x86)\python35\lib\site-packages\ipykernel_launcher.py:1: RuntimeWarning: divide by zero encountered in true_divide
"""Entry point for launching an IPython kernel.
d:\program files (x86)\python35\lib\site-packages\ipykernel_launcher.py:1: RuntimeWarning: invalid value encountered in true_divide
"""Entry point for launching an IPython kernel. array([ 0.09756098, 1. , 1. , inf, nan])
# 在这里出现了nan,表示这不是个数
inf和nan,在科学计算或者金融分析里会经常出现
# 去除掉nan和inf (np.isnan(f)) | (np.isinf(f))
array([False, False, False, True, True], dtype=bool) f[~((np.isnan(f)) | (np.isinf(f)))]
array([ 0.09756098, 1. , 1. ])
二元函数(有两个数组)
add, substract, multiply, divide, power, mod, maximum, mininum,
a=np.arange(1,6)
a
array([1, 2, 3, 4, 5]) b=np.array([5,4,3,2,1])
b
array([5, 4, 3, 2, 1]) # 求两个数组相对应位置上最大的值
np.maximum(a,b)
array([5, 4, 3, 4, 5]) # 求两个数组相对应位置上最小的值
np.minimum(a,b)
array([1, 2, 3, 2, 1])
数学和统计方法
- sum 求和
- cumsum 到当前位置的累加和
- mean 求平均数
- std 求标准差
- var 求方差
- min 求最小值
- max 求最大值
- argmin 求最小值索引
- argmax 求最大值索引
a=np.arange(1,6)
a
array([1, 2, 3, 4, 5]) #求和 sum
a.sum()
15 # mean 求平均数
a.mean(dtype="int")
3 # var 求方差
a.var()
2.0 # min 求最小值
a.min()
1 #max 求最大值
a.max()
5 # argmin 求最小值索引
a.argmin()
0 # argmax 求最大值索引
a.argmax()
4 # cumsum 到当前位置的累加和
a.cumsum()
array([ 1, 3, 6, 10, 15], dtype=int32) np.array([45,23,2,23,67]).cumsum()
array([ 45, 68, 70, 93, 160], dtype=int32)
随机数生成
- rand 给定形状产生随机数组(0到1之间的数)
- randint 给定形状产生随机整数
- choice 给定形状产生随机选择
- shuffle 与random.shuffle相同
- uniform 给定形状产生随机数组
与普通的random的主要区别是,np.random可以产生一组数据(一维和二维)
random.uniform(10,20)
10.594205287384712 a=[1,2,3,4,5]
#打乱顺序
random.shuffle(a)
a
[3, 4, 5, 2, 1] random.shuffle(a)
a
[2, 4, 5, 1, 3]
普通random无法生成一组数据
randint
np.random.randint(10,20)
array([18, 12]) #生成一组数据,(起始,终止,个数)
np.random.randint(10,20,10)
array([13, 17, 10, 13, 14, 16, 18, 12, 15, 12]) #生成一组二维数据,(起始,终止,个数)
np.random.randint(10,20,(3,5))
array([[10, 12, 16, 15, 10],
[12, 14, 10, 12, 18],
[18, 11, 14, 16, 17]])
rand
np.random.rand()
0.8208554893902571 #随机生成3个数据(0-1)
np.random.rand(3)
array([ 0.93538901, 0.48978714, 0.21131596]) #生成3行10列数据(0-1)
np.random.rand(3,10)
array([[ 0.82983877, 0.69613344, 0.75428212, 0.66390361, 0.71978929,0.7397342 , 0.48625134, 0.37076108, 0.78471486, 0.67581659],
[ 0.87354512, 0.62750562, 0.45085505, 0.85884771, 0.63135412,0.30152951, 0.25872745, 0.18371778, 0.45462829, 0.151934 ],
[ 0.7339555 , 0.57848048, 0.58641752, 0.1918355 , 0.1856244 ,0.70320558, 0.00698433, 0.83944858, 0.06223079, 0.09933519]])
choice
np.random.choice([1,2,3,4,5])
4 #从列表[1,2,3,4,5]中随机生成3个数字
np.random.choice([1,2,3,4,5],3)
array([3, 5, 4]) #从列表[1,2,3,4,5]中随机生成3行5列数据
np.random.choice([1,2,3,4,5],(3,5))
array([[3, 3, 2, 1, 1],
[2, 2, 1, 4, 2],
[1, 5, 2, 3, 2]])
shuffle
a=np.array([4,5,6,7,2,2])
a
array([4, 5, 6, 7, 2, 2]) np.random.shuffle(a)
a
array([6, 4, 2, 7, 2, 5]) b=a.reshape(3,2)
b
array([[6, 4],[2, 7],[2, 5]]) # 会改变b本身的顺序
np.random.shuffle(b)
b
array([[2, 7],[6, 4],[2, 5]])
uniform
np.random.uniform()
0.6928688148309079 #从1到10中随机生成数字
np.random.uniform(1,10)
9.424335766584397 #从1到10中随机生成3行2列的数据
np.random.uniform(1,10,(3,2))
array([[ 8.5293206 , 2.76769189],
[ 2.75080559, 7.46898322],
[ 6.65480436, 5.74601004]])