目录
1 numpy介绍
numpy 是高效的python科学计算库
numpy 有基本的两个对象类型:
ndarray: 数组
ufunc : 方法
numpy 基本对是围绕上面两种对象展开的.
1.1 环境搭建
安装python(略)
pip 安装 numpy:
pip install numpy
conda 安装 numpy
conda install numpy
2 ndarray对象
2.1 ndarray 对象的创建
numpy.array(python 序列对象)
例如:
import numpy as np
a = np.array([1,2,3,4]) #把python 的list传给array函数创建
b = np.array((1,2,3,4)) #把python的元组传给array函数创建
多维数组也是同理:
c.np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])#创建3 行4列的二维数组
a:
[1 2 3 4]
b:
[1 2 3 4]
c:
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
数组的维数可以用数组对象的shape属性得到:
a.shape
(4,)
b.shape
(4,)
c.shape
(3, 4)
a,b 只有一个数说明是一维数组,c有两个数说明是二维数组.
shape属性也可以重新设置,前提是不改变元素的大小:
c.shape = 2,6
c:
[[ 1 2 3 4 5 6]
[ 7 8 9 10 11 12]]
当设置某个轴上的的元素的个数为 -1时,将自动计算该轴元素的个数:
c.shape = 2,-1 #等同于c.shape = 2,6
同样可以通过设置属性shape 把二维数组改变成三维数组:
c.shape = 2,2,3
c:
[[[ 1 2 3]
[ 4 5 6]]
[[ 7 8 9]
[10 11 12]]]
shape属性的设置也可以通过reshape()函数来产生新的形状的数组,而原数组不变:
d = a.reshape(2,2)
a:
[1 2 3 4]
d:
[[1 2]
[3 4]]
但这样的话a和d将共享数据存储空间,只要一个中的元素改变,另一个数组中的元素也会跟着改变.
2.2 元素类型
元素的类型可以通过属性dtype获取:
import numpy as np
a = np.array([1,2,3,4])
print("type =",a.dtype)
type = int64
可以看到a中的元素类型为int64,因为我的Python版本是64位的,如果是32位的python 那这个类型就会是int32.
我们可以在用array()创建数组时通过dtype参数指定元素类型:
import numpy as np
a = np.array([1,2,3,4],dtype=np.int32)
print("type =",a.dtype)
type = int32
np.int32 是numpy定义的新类型,dtype参数可以传python内置类型,也可以传numpy定义的新类型(注意:numpy 的数据对象的运算速度比Python内置类型的运算速度慢很多,如果有大量对单个数值运算,应避免使用numpy的数据对象).astype()函数可以将元素类型进行转换产生一个新的数组,但不会改变原数组的类型:
import numpy as np
a = np.array([1,2,3,4],dtype = np.float)
b = np.array([1,2,3,4],dtype = np.complex)
c = a.astype(np.int32)
d = b.astype(np.complex64)
print(a.dtype)
print(b.dtype)
print(c.dtype)
print(d.dtype)
float64
complex128
int32
complex64
2.3 自动产生数组
前面用Python的序列对象创建数组,但这效率非常低,下面介绍几种自动创建数组的方法:
- np.arange()
这个函数和内置的函数range非常相似.通过指定开始值和终止值(创建的数组中不包括终止值),还有步长来创建数组:
print(np.arange(0,10,1))
[0 1 2 3 4 5 6 7 8 9]
- np.linspace()
该函数指定开始值和终止值还有元素个数还有元素个数来产生数组,该函数还可以通过endpoint(默认为True,包括终止值,False是不包括)参数来决定包不包括终止值:
print(np.linspace(0,10,11,endpoint=True))
[ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
- np.logspace()
该函数指定开始值和终止值,还有元素个数来产生等比数组:
print(np.logspace(0,2,5))
[ 1. 3.16227766 10. 31.6227766 100. ]
这里的0指的是10^0 =1,2指的是 10^2 = 100,意思就是从1到100产生5个元素的等比数列,这里的底数默认位10,可以通过base参数指定底数.等比值大概为: 3.16227766
4. 其他函数
np.empty() #只创建数组形状和数据类型,不进行元素的初始化,速度快
np.zeros() #把创建的数据的元素初始化位0
np.ones()#把创建的数据的元素初始化位1
np.full() + 指定数据元素初始化的值
2.4 切片
a = np.arange(10)
print("a = ",a)
print("a[5] = ",a[5])
print("a[2:5] = ",a[2:5])
print("a[:5] = ",a[:5])
print("a[:-1] = ",a[:-1])
a = [0 1 2 3 4 5 6 7 8 9]
a[5] = 5
a[2:5] = [2 3 4]
a[:5] = [0 1 2 3 4]
a[:-1] = [0 1 2 3 4 5 6 7 8]
切边的获取的数组和原数组共享数据.
- 使用整数列表对数组元素进行存取
print(a[[2,4,6,8]])
[2 4 6 8]
使用整数列表对数组元素进行获取,列表中的值就是获取的元素的下标值,并且获取的数据不和原数据共享数据,将创建一个新的和下标数组同形状的数组
- 使用布尔数组对数组元素进行存取
a = np.arange(4)
print(a[np.array([True,False,False,True])])#这里注意布尔型的数组而不是布尔型的列表,但在numpy1.1之后的版本中布尔型列表会被当成布尔型数组.所以numpy1.1以后可以这样用:
#print(a[[True,False,False,True]])
[0 3]
获取对应数组中为True的元素组成数组,而且组成的数组不和原数组共享数据元素.
3ufunc函数
3.1 ufunc函数介绍
ufun 是一种对darray中的每一个元素进行运算的函数,因为大部分的ufunc函数都是用c语言实现的,所以他们的速度一般都很快.
x = np.linspace(0,4*np.e,10)
print("x:",x)
y = np.sin(x)
print("y:",y)
x: [ 0. 1.20812526 2.41625051 3.62437577 4.83250103 6.04062629
7.24875154 8.4568768 9.66500206 10.87312731]
y: [ 0. 0.93495254 0.66339149 -0.464246 -0.99279522 -0.24018752
0.82237121 0.82369742 -0.23792029 -0.99251273]
上述代码中,产生一个元素个数为10,从0到4*e的等差数列.然后通过np.sin函数依次计算x中每个元素的正弦值,然后组成一个新的数组.这里np.sin()函数并没有改变x中的元素的值值,而是产生新的数组.如果想要指定保存结果的数组,可以用out参数来指定.
x = np.linspace(0,4*np.e,10)
print("x:",x)
y = np.sin(x,out=x)
print("y:",y)
3.2 四则运算
np.add
a = np.arange(0,7)
b = np.arange(3,10)
print(np.add(a,b))
[ 3 5 7 9 11 13 15]
我们可以看到add函数将a,b两个数组上的对应上元素依次相加,然后组成一个新的元素.但其实还有一种更简便的方法,因为numpy中定义了各种数学元素符,所以我们可以直接用数学符号’+’ 来代替np.add()函数,上面的程序等同于:
a = np.arange(0,7)
b = np.arange(3,10)
print(a+b)
不只是加号,其他的数学符号还有比较的运算符也是一样的.(这里就不作介绍)
3.3 布尔运算
可以使用’==’, ‘<’, '>'等符号对数组进行比较,比较返回一个布尔数组,它的每个元素都是两个数组对应元素的比较结果.
import numpy as np
a = np.array([4,5,6]) < np.array([6,5,4])
print(a)
[ True False False]
python 中的布尔运算使用and,or,not等关键字分别表示与,或,非.这些关键字无法被重载所以numpy只能使用相应的ufunc函数进行,他们的函数名字都是以logical_开头:
np.logical_and #与
np.logical_not #或
np.logical_or #非
np.logical_xor #异或
3.4 广播
我们使用ufunc函数对两个数组进行计算时,ufunc函数会对这两个数组的对应元素进行计算,因此它要求这两个数组的形状相同,如果形状不同会进行如下的关播:
- 让所有输入数组都向其中维数最多的数组看齐,shape属性中不足的部分都通过在前面加1补齐.
- 输出数组的shape属性是输入数组的shape属性的各个轴上的最大值
- 如果输入数组的某个轴的长度为1或与输出数组的对应抽的长度相同,这个数组能够用来计算,否则出错.
- 当输入数组的某个轴的长度为1时,沿着此轴运算时都用此轴上的第一组值.
来一个例子说明一下:
a = np.arange(0,60,10).reshape(-1,1)
print("a = ",a,a.shape)
b = np.arange(0,5)
print("b = ",b,b.shape)
c = a + b
print('c = ',c,c.shape)
a = [[ 0]
[10]
[20]
[30]
[40]
[50]] (6, 1)
b = [0 1 2 3 4] (5,)
c = [[ 0 1 2 3 4]
[10 11 12 13 14]
[20 21 22 23 24]
[30 31 32 33 34]
[40 41 42 43 44]
[50 51 52 53 54]] (6, 5
-
a的形状为(6,1),b的形状为(5,),因为维数不同,根据第一条规则,需要让b的shape属性向a看齐,于是在b的shape属性前面加一个1,b的shape就变为(1,5),b数组变为:[[0 1 2 3 4]]
-
现在a的shape为(6,1),b的shape(1,5),根据规则2,输出的数组各个轴的长度为输入数组的各个轴的长度的最大值,因此c的shape应该为(6,5)
-
由于b的第0轴的长度为1,而a的第0轴的长度为8,为了让它们在第0轴上能够相加,需要将b的第0轴的长度拓展为6,然后b就为:
[[0 1 2 3 4],
[0 1 2 3 4],
[0 1 2 3 4],
[0 1 2 3 4],
[0 1 2 3 4],
[0 1 2 3 4],]
- 而现在的a的shape为(6,1),b的shape为(6,5),a的第1轴长度为1,而b的第1轴的长度为5,为了让a,b在第1轴能相加,所以a的第1轴需要拓展成5,然后a的shape就变为(6,5),a变为:
[[ 0,0,0,0,0]
[10,10,10,10,10]
[20,20,20,20,20]
[30,30,30,30,30]
[40,40,40,40,40]
[50,50,50,50,50]
- 现在a的shape和b的shape相同了,然后对应位置上的个元素相加就会得到c.
上面就是广播的过程,需要注意的是上面的额例子中a和b数组的原数据都没有变,上面只是为了说明这个过程才引入a,b拓展,变化的过程,实际的过程是会产生临时变量来代替上面的a,b的位置.
3.5 多维数组的下标存取
多维数组的下标是一个长度和数组的维数相同的元组.如果大与数组的维数就会出错,如果小与数组就会在下标元组后面补’:’.如果它的各元素有如下几种类型:切片,整数,整数数组和布尔型数组,如果不是这些数组就会转换成整数数组.而且如果切片和整数,那么用他作为下标得到的是原始数组的一个视图.