python科学计算笔记 - numpy基础

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的序列对象创建数组,但这效率非常低,下面介绍几种自动创建数组的方法:

  1. np.arange()
    这个函数和内置的函数range非常相似.通过指定开始值和终止值(创建的数组中不包括终止值),还有步长来创建数组:
     print(np.arange(0,10,1))
     [0 1 2 3 4 5 6 7 8 9]
  1. np.linspace()
    该函数指定开始值和终止值还有元素个数还有元素个数来产生数组,该函数还可以通过endpoint(默认为True,包括终止值,False是不包括)参数来决定包不包括终止值:
    print(np.linspace(0,10,11,endpoint=True))
    [ 0.  1.  2.  3.  4.  5.  6.  7.  8.  9. 10.]
  1. 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]

切边的获取的数组和原数组共享数据.

  1. 使用整数列表对数组元素进行存取
     print(a[[2,4,6,8]])
     [2 4 6 8]

使用整数列表对数组元素进行获取,列表中的值就是获取的元素的下标值,并且获取的数据不和原数据共享数据,将创建一个新的和下标数组同形状的数组

  1. 使用布尔数组对数组元素进行存取
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函数会对这两个数组的对应元素进行计算,因此它要求这两个数组的形状相同,如果形状不同会进行如下的关播:

  1. 让所有输入数组都向其中维数最多的数组看齐,shape属性中不足的部分都通过在前面加1补齐.
  2. 输出数组的shape属性是输入数组的shape属性的各个轴上的最大值
  3. 如果输入数组的某个轴的长度为1或与输出数组的对应抽的长度相同,这个数组能够用来计算,否则出错.
  4. 当输入数组的某个轴的长度为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
  1. a的形状为(6,1),b的形状为(5,),因为维数不同,根据第一条规则,需要让b的shape属性向a看齐,于是在b的shape属性前面加一个1,b的shape就变为(1,5),b数组变为:[[0 1 2 3 4]]

  2. 现在a的shape为(6,1),b的shape(1,5),根据规则2,输出的数组各个轴的长度为输入数组的各个轴的长度的最大值,因此c的shape应该为(6,5)

  3. 由于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],]
  1. 而现在的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] 
  1. 现在a的shape和b的shape相同了,然后对应位置上的个元素相加就会得到c.

上面就是广播的过程,需要注意的是上面的额例子中a和b数组的原数据都没有变,上面只是为了说明这个过程才引入a,b拓展,变化的过程,实际的过程是会产生临时变量来代替上面的a,b的位置.

3.5 多维数组的下标存取

多维数组的下标是一个长度和数组的维数相同的元组.如果大与数组的维数就会出错,如果小与数组就会在下标元组后面补’:’.如果它的各元素有如下几种类型:切片,整数,整数数组和布尔型数组,如果不是这些数组就会转换成整数数组.而且如果切片和整数,那么用他作为下标得到的是原始数组的一个视图.

发布了18 篇原创文章 · 获赞 1 · 访问量 205

猜你喜欢

转载自blog.csdn.net/andyonlines/article/details/100057925
今日推荐