最近在看张若愚老师的《Python科学计算》,也算是对Python的基本功进行一次锻炼,看着就记下笔记,这里开个系列来分享一下个人笔记,文章内容都是markdown直接编译过来的,所以排版也没多花心思了。
NumPy提供了两种基本的对象: ndarray和ufunc
import numpy as np
利用命名行直接查看说明文档和用法示例,输入函数名并添加一个“?”符号即可
np.array?
常用的主要有arange()、linspace()、logspace()
np.arange(0,1,0.1)
array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
np.linspace(0,1,10) # 步长为1/9
array([0. , 0.11111111, 0.22222222, 0.33333333, 0.44444444,
0.55555556, 0.66666667, 0.77777778, 0.88888889, 1. ])
np.linspace(0,1,10,endpoint=False) # 步长为1/10
array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
np.logspace(0,2,5)
array([ 1. , 3.16227766, 10. , 31.6227766 ,
100. ])
还有很多,比如:
直接对创建好的ndarray对象进行赋值储存,和列表一样都可以进行切片,和列表不同的是,通过切片获取的新数组是原始数组的一个视图,它与原始数组共享同一块数据存储空间,意味着只要修改了视图的内容,原数组也是会跟着变化的:
a = np.arange(10)
print(a)
b = a[3:7] # 数组a 和数组b 共同一块数据存储空间
print(b)
b[0]= 999 # 将b的第1个元素修改为999
print(b)
print(a) # a的元素也被修改了
[0 1 2 3 4 5 6 7 8 9]
[3 4 5 6]
[999 4 5 6]
[ 0 1 2 999 4 5 6 7 8 9]
对应的,除了用切片来截取元素,还可以用整数列表、整数数组和布尔数组等几种高级下标存取方法。
x = np.arange(5,1,-1)
print(x)
# 整数列表存取
a1 = x[[1,2,3]]
print(a1)
# 整数数组存取
a2 = x[np.array([[3,3,1,0],[3,3,-3,0]])]
print(a2)
# 布尔数组存取
a3 = x[np.array([True,False,False,False])]
print(a3)
[5 4 3 2]
[4 3 2]
[[2 2 4 5]
[2 2 4 5]]
[5]
多维数组的存取和一维数组类似,因为多维数组有多个轴,因此它的下标需要用多个值表示。NumPy采用元组(tuple)作为数组的下标,元组中的每个元素和数组的每个轴对应。图2-1显示了一个形状为(6,6)的数组a,图中用不同颜色和线型标识出各个下标对应的选择区域。
大家可能对于第4个会比较困惑,这个其实是slice对象方法,其中最后那个‘2’是间隔步长。
ufunc是universal function的缩写,它是一种能对数组中每个元素进行操作的函数。NumPy内置的许多ufunc函数都是在C语言级别实现的,因此它们的计算速度非常快。让我们先看一个例子:
x = np.linspace(0,2*np.pi,10)
print(x)
print('---------------------------------')
y = np.sin(x)
print(y)
[0. 0.6981317 1.3962634 2.0943951 2.7925268 3.4906585
4.1887902 4.88692191 5.58505361 6.28318531]
---------------------------------
[ 0.00000000e+00 6.42787610e-01 9.84807753e-01 8.66025404e-01
3.42020143e-01 -3.42020143e-01 -8.66025404e-01 -9.84807753e-01
-6.42787610e-01 -2.44929360e-16]
先用linspace()产生一个从0到2π的等差数组,然后将其传递给np.sin()函数计算每个元素的正弦值。由于np.sin()是一个ufunc函数,因此在其内部对数组x的每个元素进行循环,分别计算它们的正弦值,并返回一个保存各个计算结果的数组。 此外,使用ufunc函数的速度也是比Python标准库要快:
import time
import math
import numpy as np
x = [i*0.001 for i in range(10000000)]
start = time.clock()
for i,t in enumerate(x): # 枚举函数
x[i]=math.sin(t)
print ('math.sin:',time.clock()-start)
x = [i*0.001 for i in range(10000000)]
x = np.array(x)
start = time.clock()
np.sin(x,x)
print('numpy.sin',time.clock()-start)
math.sin: 3.394713154884201
numpy.sin 0.01636017985525484
如果没有指定out参数,那么将创建一个新的数组来保存计算结果。如果指定了第三个参数out,就不产生新的数组,而是直接将结果保存到指定的数组中。
使用“==”、“>”等比较运算符对两个数组进行比较,将返回一个布尔数组,它的每个元素值都是两个数组对应元素的比较结果。
由于Python中的布尔运算使用and、or和not等关键字,它们无法被重载,因此数组的布尔运算只能通过相应的ufunc函数进行。这些函数名都以“logical_”开头,在IPython中使用自动补全功能可以很容易地找到它们:
np.logical # 此时按下Tab键即可自动补全
np.logical_and
np.logical_not
np.logical_or
np.logical_xor
—End—