Python科学计算核心:NumPy数组与矩阵运算详解
本文深入解析Python中NumPy库的核心用法,涵盖ndarray对象的创建、属性获取(shape、size、dtype)、数组生成方法(arange、linspace)及多维数组的形状重塑。详细对比了element-wise运算与矩阵乘法,介绍了matrix类的特性与潜在风险,并讲解了数据提取、浅/深拷贝机制及遍历技巧,助力开发者高效进行高性能数值计算。
前言
NumPy是Python生态中处理大型矩阵运算的高效数学库。它支持在Python环境中执行向量和矩阵计算,其底层大量函数由C语言实现,从而提供了普通Python代码难以企及的运行速度。这种性能优势部分源于矩阵元素具有统一的数据类型,从而避免了运算过程中的频繁类型检测开销。
矩阵基础
在NumPy库中,我们使用数组(array)来代表向量、矩阵以及更高维度的数据结构。这些结构均由数组构建:一维数据直接使用单个数组表示,而二维数据则表现为数组中嵌套数组的形式。
创建
# coding: utf-8 import numpy as np a = np.array([ [1.73, 1.68, 1.71, 4], [1, 2, 3, 4], [1, 2, 3, 4] ]) print type(a) # <type 'numpy.ndarray'>
ndarray(N-dimensional array object)即N维数组对象。示例中展示了一个包含3行4列的二维数组结构。
形状
可以通过访问数组的shape属性来获取其大小信息:
print a.shape # (3L,4L)
数组中包含的元素总数可以通过访问ndarray.size属性得到:
print a.size # 12
利用ndarray的dtype属性,我们可以查看数组中元素的具体数据类型:
print a.dtype # float64
可以通过修改shape属性来重新设定矩阵的形状,或者使用reshape方法创建一个尺寸改变的新数组,此时原数组的shape属性保持不变:
a.shape = 4, 3 b = a.reshape((2, 6)) # 尽管b的形状是新的,但是a和b是共享数据存储内存区域的,如果b[0][1] = 8 那么a[0][1] 也会是8
数组生成
可以使用np.arange 函数来创建数组,其参数用法与Python内置的range函数类似:
x = np.arange(0, 10, 1) # arguments: start, stop, step
此外,还可以利用np.linspace函数来创建等差数列:
x = np.linspace(1, 10, 5) # arguments: start, stop, num元素个数 # [ 1. 3.25 5.5 7.75 10. ] # np.logspace 是创建等比数列
矩阵运算
当变量直接参与运算符时,操作符的优先级保持不变:
a = np.random.rand(5, 5) b = np.random.rand(5, 5) print a + b print a - b print a * b print a / b print a ** 2 print a < b print a > b
在一个数组中,除了dot() 函数外,其他上述操作均属于单元操作(element-wise operations)。
np_arr = np.array([2,3,34,5,5]) print np.mean(np_arr) # 平均数 print np.median(np_arr) # 中位数 print np.corrcoef(a[0], a[1]) # 判断两个轴的数据是否有相关性 print np.std(np_arr) # 标准差
数据提取
切片索引的语法格式如下:M[lower:upper:step]
a = np.array([1,2,3,4,5]) a[1:3] # array([2, 3]) # 进行切片赋值时,原数组会被修改 a[1:3] = [-2, -3] # array([ 1, -2, -3, 4, 5]) b = np.random.rand(5, 5) b[1:4, 1:4] # 提取 1~4 行,1~4列 b > 0.1 #array([False, False, False, ...]) # 因此要提取可以用, 这是利用了布尔屏蔽这个特性 b[ b > 0.1 ] # where()函数是另一个有用的方式,当需要以特定条件来检索数组元素的时候。只需要传递给它一个条件,它将返回符合条件的元素列表。 c = np.where(b > 0.1)
矩阵运算
与Matlab不同,NumPy对多维数组的运算默认并非执行矩阵乘法。若需对数组进行矩阵运算,必须调用相应的专用函数。
matrix对象
NumPy库提供了matrix类,通过该类创建的矩阵对象在加减乘除运算时默认采用矩阵方式计算,因此其用法与Matlab非常相似。然而,由于NumPy中同时存在ndarray和matrix两种对象,用户容易混淆二者。这违背了Python“显式优于隐式”的设计原则,因此在编写复杂程序时并不推荐使用matrix类。
>>> a = np.matrix([[1,2,3],[5,5,6],[7,9,9]]) >>> a*a**-1 matrix([[ 1.00000000e+00, 1.66533454e-16, -8.32667268e-17], [ -2.77555756e-16, 1.00000000e+00, -2.77555756e-17], [ 1.66533454e-16, 5.55111512e-17, 1.00000000e+00]])
可以通过m = np.matrix(a)将数组转换为矩阵,使用m.T属性可以获得m的转置矩阵。
矩阵求逆
m.I * m => matrix([[ 1.00000000e+00+0.j, 4.44089210e-16+0.j], [ 0.00000000e+00+0.j, 1.00000000e+00+0.j]])
浅拷贝与深拷贝
为了追求高性能,Python中的赋值操作通常不拷贝底层对象,这被称为浅拷贝。若需进行深拷贝,可使用copy函数:
b = copy(a)
遍历数组元素
通常情况下,应尽可能避免直接遍历数组元素,因为迭代操作相比向量运算要慢得多。但在某些不可避免需要迭代的场景中,使用Python的for循环是最便捷的方式:
v = np.array([1,2,3,4])
for element in v:
print(element)
M = np.array([[1,2], [3,4]])
for row in M:
print("row", row)
for element in row:
print(element)
总结
以上即为关于Python科学计算中NumPy库的全部内容,希望本文的内容能对大家的编程学习或工作有所帮助。如有任何疑问,欢迎留言交流。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









