Numpy是python的一种开源的数值计算扩展。这种工具可以用来储存和处理大型矩阵,比python自身的嵌套列表结构要高效的多。Numpy提供了许多高级的数值编程工具。Numpy的一个重要特性是他的数据组计算,是我们做的数据必不可少的一个包。
导入python库使用关键字import,后面可以自定义库的简称,但是一般都将Numpy命名为np,pandas命名为pd。
使用前一定要先导入Numpy包,导入的方法有以下几种:
1.import numpy
2.import numpy as np
3.form numpy import
Numpy的数组对象及其索引
数组上的数学操作
假如我们想将列表中的每个元素增加1,但列表不支持这样的操作:
a=[1,2,3,4]
a+1
print(a+1) #列表不支持这样的操作,报错
a=[1,2,3,4]
[x+1 for x in a]
print([x+1 for x in a]) #列表只能这样,才能将每个元素增加1
将两个列表元素对应相加
a=[1,2,3,4]
b=[2,3,4,5]
print(a+b) #这是两个列表拼接
#结果:
[1, 2, 3, 4, 2, 3, 4, 5]
a=[1,2,3,4]
b=[2,3,4,5]
print([x+y for (x,y) in zip(a,b)]) #两个列表元素对应相加
#结果:
[3, 5, 7, 9]
这样的操作比较麻烦,而且在数据量特别大的时候会非常耗时间。如果我们使用Numpy,就会变得简单。
例:建一个数组,在每个元素上加1
import numpy as np
a=np.array([1,2,3,4])
print(a)
#结果:
[1 2 3 4]
b=a+1
print(b)
#结果:
[2 3 4 5]
例:两个数组元素对应相加
import numpy as np
a=np.array([1,2,3,4])
b=np.array([2,3,4,5])
print(a+b)
#结果:
[3 5 7 9]
产生数据的方式:
从列表产生数组:
import numpy as np
list=[0,1,2,3]
a=np.array(list)
print(a)
从列表传入:
import numpy as np
a=np.array([1,2,3,4])
print(a)
生成0数组:
import numpy as np
a=np.zeros(5)
print(a)
生成全1的数组:
import numpy as np
a=np.ones(5,dtype='int')
print(a)
可以使用fill方式将数组设定为指定值:
fill会自动进行取整,如果想变成小数,强制进行转换。
import numpy as np
a=np.array([1,2,3,4])
a.fill(5)
print(a)
a=a.astype('float') #进行转换
与列表不同,数组中要求所有元素的dtype是一样的,如果传入参数的类型与数组类型不一样,需要按照已有的类型进行转换。还可以使用一些特定的方法生成特殊的数组
生成整数序列:
import numpy as np
a=np.arange(1,10,2) #这个里面括号是左闭右开,2是步长
print(a)
#结果
[1 3 5 7 9]
生成等差序列:
import numpy as np
a=np.linspace(1,10,10) #这里括号是双闭的,第二个10是有10个元素
print(a)
#结果
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
生成随机数:
import numpy as np
a=np.random.rand(10) #0-1随机生成10个元素
print(a)
#结果:
[0.49364252 0.91044541 0.40119152 0.33678082 0.85807913 0.62023705 0.51507097 0.52876382 0.88644618 0.99546188]
import numpy as np
a=np.random.randn(10) #随机生成10个正太分布
print(a)
#结果:
[ 0.46166455 0.78830024 0.55848265 1.0556776 0.92748966 -0.07222513 -1.91709458 0.76603085 0.63207431 0.03019785]
import numpy as np
a=np.random.randint(1,10,10) #随机生成10个整数
print(a)
#结果:
[5 6 2 2 5 3 1 7 5 9]
数组属性
查看类型:
print(type(a)) #查看类型
查看数组中的数据类型:
print(a.dtype) #查看数组的数据类型
查看形状,会返回一个元组,每个元素代表这一维的元素数目:
print(a.shape)
查看数组里面元素数目:
print(a.size)
查看数组维度:
print(a.ndim)
索引与切片
和列表相似,数组也支持索引和切片操作。
索引第一个元素:
import numpy as np
a=np.array([0,1,2,3])
print(a[0])
#结果:
0
修改第一个元素的值:
import numpy as np
a=np.array([0,1,2,3])
a[0]=10
print(a)
#结果:
[10 1 2 3]
切片,支持负索引:
import numpy as np
a=np.array([11,12,13,14,15])
print(a[1:3])
print(a[1:-2])
print(a[-4:3])
#结果:
[12 13]
[12 13]
[12 13]
省略参数:
import numpy as np
a=np.array([11,12,13,14,15])
print(a[-2:])
print(a[::2])
#结果:
[14 15]
[11 13 15]
例:假设我们记录一部电影的累计票房:
import numpy as np
ob=np.array([21000,21800,22240,23450,25000])
print(ob)
#结果:
[21000 21800 22240 23450 25000]
可以计算每天的票房:
ob2=ob[1:]-ob[:-1]
print(ob2)
#结果:
[ 800 440 1210 1550]
多维数组及其属性
array还可以用来生成多维数组:
import numpy as np
a=np.array([[0,1,2,3],[10,11,12,13]])
print(a)
#结果:
[[ 0 1 2 3]
[10 11 12 13]]
事实上我们传入的是一个一列表为元素的列表,最终得到一个二维数组。
查看形状:
print(a.shape)
#结果:
(2, 4)
查看总的元素个数:
print(a.size)
#结果:
(2, 4)
查看维数:
print(a.ndim)
#结果:
2
多维数组索引
对于二维数组,可以传入两个数字来索引:
import numpy as np
a=np.array([[0,1,2,3],[10,11,12,13]])
print(a[1,3])
#结果:
13
其中,1是行索引,3是列索引,中间用逗号隔开,事实上,python会将他们看成一个元组(1,3),然后按照顺序进行对应。
可以利用索引给他赋值:
a[1,3]=-1
print(a)
#结果:
[[ 0 1 2 3]
[10 11 12 -1]]
事实上,我们还可以使用单个索引来索引一整行内容:
print(a[1])
#结果:
[10 11 12 -1]
print(a[:,1]) #按列输出,行索引在逗号前面,列索引在逗号后面
#结果:
[ 1 11]
python会将这单个元组当成对第一维的索引,然后返回对应的内容。
多维数组切片
多维数组,也支持切片操作
想得到第一行的第4和第5两个元素:
import numpy as np
a=np.array([[0,1,2,3,4,5],[10,11,12,13,14,15],[20,21,22,23,24,25],[30,31,32,33,34,35],[40,41,42,43,44,45],[50,51,52,53,54,55]])
print(a)
print(a[0,4:])
#结果:
[[ 0 1 2 3 4 5]
[10 11 12 13 14 15]
[20 21 22 23 24 25]
[30 31 32 33 34 35]
[40 41 42 43 44 45]
[50 51 52 53 54 55]]
[4 5]
得到最后两行的最后两列:
print(a[4:,4:])
#结果:
[[44 45]
[54 55]]
得到第三列:
print(a[:,2])
#结果:
[ 2 12 22 32 42 52]
每一维都支持切片的规则,包括负索引,省略:
[lower:upper:step]
例如,取出3,5行的奇数列:
print(a[2::2,::2])
#结果:
[[20 22 24]
[40 42 44]]
切片是引用
切片在内存中使用的是引用机制。
import numpy as np
a=np.array([0,1,2,3,4])
b=a[2:4]
print(b)
#结果:
[2 3]
b[0]=10
print(a) #[2 3]中将10赋值给b[0]
#结果:
[ 0 1 10 3 4]
引用机制意味着,python并没有为b分配新的空间来存储它的值,而是让b指向a所分配的内存空间,因此,改变b会改变a的值:
而这种现象在列表中并不会出现:
a=[1,2,3,4,5]
b=a[2:4]
b[0]=10 #列表中并没有将10赋值给b[0]
print(a)
#结果:
[1, 2, 3, 4, 5]
这样的好处在于对于很大的数组,不用大量复制多余的值,节约了空间。
缺点在于可能出现改变一个值改变另一个值得情况。
一个解决方法是使用copy()方法产生一个复制,这个复制会申请新的内存:
import numpy as np
a=np.array([0,1,2,3,4])
b=a[2:4].copy #在新申请的内存中将a[2:4]赋值给b
print(a) #这里输出的是原来的内存
#结果:
[0 1 2 3 4]
花式索引
切片只支持连续或者等间隔的切片操作,要实现任意位置的操作,需要使用花式索引fancy slicing。
一维花式索引
与range函数类似,我们可以使用arange函数来产生等差数组。
import numpy as np
a=np.arange(0,100,10)
print(a)
花式索引需要指定索引位置:
index=[1,2,-3]
y=a[index]
print(y)
#结果:
[10 20 70]
还可以使用布尔数组来花式索引:
mask=np.array([0,2,2,0,0,1,0,0,1,0],dtype=bool)
print([mask])
#结果:
[array([False, True, True, False, False, True, False, False, True,
False])]
mask必须是布尔数组。长度必须和数组长度相等。
print(a[mask])
#结果:
[10 20 50 80]
二维花式索引
对于花式索引,我们需要给定行和列的值:
import numpy as np
a=np.array([[0,1,2,3,4,5],[10,11,12,13,14,15],[20,21,22,23,24,25],[30,31,32,33,34,35],[40,41,42,43,44,45],[50,51,52,53,54,55]])
print(a)
#结果:
[[ 0 1 2 3 4 5]
[10 11 12 13 14 15]
[20 21 22 23 24 25]
[30 31 32 33 34 35]
[40 41 42 43 44 45]
[50 51 52 53 54 55]]
返回的是一条次对角线上的5个值。
b=a[(0,1,2,3,4),(1,2,3,4,5)]
print(b)
#结果:
[ 1 12 23 34 45]
返回的是最后三行的第1,3,5列。
b=a[3:,[0,2,4]]
print(b)
#结果:
[[30 32 34]
[40 42 44]
[50 52 54]]
也可以使用mask进行索引:
mask=np.array([1,0,1,0,0,1],dtype=bool)
print(a[mask,2])
#结果:
[ 2 22 52] #第三列中[2,12,22,32,42,52],对应[1,0,1,0,0,1]。可输出[2 32 52]
与切片不同,花式索引返回的是原对象的一个复制而不是引用。
“不完全”索引
只给定行索引的时候,返回整行:
y=a[:3]
print(y)
#结果:
[[ 0 1 2 3 4 5]
[10 11 12 13 14 15]
[20 21 22 23 24 25]]
这个时候也可以使用花式索引取出第2,3,5行:
con=np.array([0,1,1,0,1,0],dtype=bool)
b=a[con]
print(b)
#结果:
[[10 11 12 13 14 15]
[20 21 22 23 24 25]
[40 41 42 43 44 45]]
where语句
where(array)
where 函数会返回所有非零元素的索引。
一维数组
先看一维的例子:
import numpy as np
a=np.array([0,12,5,20])
判断数组中的元素是不是大于10:
print(a>10)
#结果:
[False True False True]
数组中所有大于10的元素的索引位置:
b=np.where(a>10)
print(b)
#结果:
(array([1, 3], dtype=int64),)
注意到where的返回值是一个元组。返回的是索引位置,索引[1,3]大于10的数
也可以直接用数组操作。
print(a[a>10])
#结果:
[12 20]
b=a[np.where(a>10)]
print(b)
#结果:
[12 20]
2.数组类型
类型转换
import numpy as np
a=np.array([1.5,-3],dtype=float)
print(a)
#结果:
[ 1.5 -3. ]
asarray函数
import numpy as np
a=np.array([1,2,3])
print(np.asarray(a,dtype=float))
#结果:
[1. 2. 3.]
astype方法
import numpy as np
a=np.array([1,2,3])
b=a.astype(float)
print(b)
#结果:
[1. 2. 3.]
b[0]=0.5
print(b)
#结果:
[0.5 2. 3. ]
print(a)
#结果:
[1 2 3]
3.数组操作
以豆瓣10部最高电影为例:
数组排序
sort函数
argsort函数
argsort返回从小到大的排序在数组中的索引位置:
求和
最大值
最小值
均值
标准差
相关系数矩阵
多维数组操作
数组形状
import numpy as np
a=np.arange(6)
a.shape=2,3 #2行3列 print(a)
#结果:
[[0 1 2] [3 4 5]]
与之对应的方法是reshape,但它不会修改原来数组的值,而是返回一个新的数组:
print(a.reshape(2,3))
print(a)
#结果:
[[0 1 2]
[3 4 5]]
[0 1 2 3 4 5]
转置
a.shape=2,3
print(a)
#结果:
[[0 1 2]
[3 4 5]]
print(a.T)
#结果:
[[0 3]
[1 4]
[2 5]]
print(a.transpose())
#结果:
[[0 3]
[1 4]
[2 5]]
数组连接
有时我们需要将不同的数组按照一定的顺序连接起来:
concatenate((a0,a1,......,aN),axis=0)
注意,这些数组要用()包括到一个元组中去。
除了给定的轴外,这些数组其他轴的长度必须是一样的。
import numpy as np
x=np.array([[0,1,2],[10,11,12]])
y=np.array([[50,51,52],[60,61,62]])
print(x.shape)
print(y.shape)
#结果:
(2, 3)
(2, 3)
默认沿着第一维进行连接:
z=np.concatenate((x,y))
print(z)
#结果:
[[ 0 1 2]
[10 11 12]
[50 51 52]
[60 61 62]]
沿着第二维进行连接:
z=np.concatenate((x,y),axis=1)
print(z)
#结果
[[ 0 1 2 50 51 52]
[10 11 12 60 61 62]]
注意到这里x和y的形状是一样的,还可以它们连接成三维的数组,但是concatenate不能提供这样的功能,不过可以这样:
z=np.array((x,y))
print(z)
#结果:
[[[ 0 1 2]
[10 11 12]]
[[50 51 52]
[60 61 62]]]
事实上,Numpy提供了分别对应这三种情况的函数:
-
vstack
-
hstack
-
dstack
numpy内置函数