数学游戏与科学可视化:NumPy与SciPy的应用
1. NumPy数组的方法和属性
在Python的数值计算领域,NumPy是一个强大的工具。数组作为NumPy中的重要对象,具有方法(函数)和属性(变量)。我们可以使用IPython通过Tab键的字符补全功能列出对象的方法和属性,也可以使用以下代码:
import numpy
[m for m in dir(numpy.ndarray) if not(m.startswith('__'))]
运行上述代码后,会得到一串数组的方法和属性列表,如
['T', 'all', 'any', 'argmax', ... , 'view']
。下面我们来详细介绍部分常用的方法和属性,它们被分为不同的类别,方便查看。
1.1 逻辑类方法
| 函数 | 描述 | 示例 |
|---|---|---|
| all() |
如果数组
a
的所有元素都为真(非零),则返回
True
|
arange(10).all()
返回
False
,因为第一个元素是零;
arange(-5, -2).all()
返回
True
|
| any() |
如果数组
a
中至少有一个元素为真(非零),则返回
True
|
arange(10).any()
返回
True
|
| nonzero() |
返回数组
a
中非零元素的索引元组
|
arange(3).nonzero()
返回
(array([1, 2], dtype=int64),)
|
1.2 索引类方法
| 函数 | 描述 | 示例 |
|---|---|---|
| sort() |
对数组
a
中的元素进行排序
|
a = arange(3, 0, -1)
将
a
设置为
array([3, 2, 1])
;
a.sort()
将
a
变为
array([1, 2, 3])
|
| searchsorted(x) |
返回插入
x
的索引,以保持数组的顺序,假设数组
a
已经排序
|
arange(4).searchsorted(1.5)
返回
2
|
1.3 修改类方法
| 函数 | 描述 | 示例 |
|---|---|---|
| clip(min, max) |
如果数组
a
的元素小于
min
,则返回
min
;如果大于
max
,则返回
max
;否则返回该元素
|
arange(5).clip(1, 3)
返回
array([1, 1, 2, 3, 3])
|
| compress(cond) |
返回一个数组,其元素满足
cond
指定的条件,等同于
a[cond]
|
a = arange(10)
;
a.compress(a > 5)
返回
array([6, 7, 8, 9])
;
a[a > 5]
也返回
array([6, 7, 8, 9])
|
| fill(x) |
将数组的所有值设置为
x
,等同于
a[:] = x
|
a = zeros([2, 2])
;
a[:] = -1
将
a
设置为
array([[-1., -1.], [-1., -1.]])
|
1.4 数学类方法
假设
a = array([1, 1j, -1])
,也可以表示为
a = exp(1j*pi*arange(3)/2)
。
| 函数 | 描述 | 示例 |
| — | — | — |
| cumprod() | 累积乘积,每个元素是数组中前面元素的乘积 |
a.cumprod()
返回
array([ 1.+0.j, 0.+1.j, 0.-1.j])
|
| cumsum() | 累积求和,每个元素是数组中前面元素的和 |
a.cumsum()
返回
array([ 1.+0.j, 1.+1.j, 0.+1.j])
|
| real & imag | 数组
a
中元素的实部和虚部 |
a.imag
返回
array([ 0., 1., 0.])
;
a.real
返回
array([ 1., 0., -1.])
|
| conj() | 数组
a
的复共轭(虚部取反,行列转置) |
a[1].conj()
返回
-1j
|
| max(), min() | 数组
a
的最大值和最小值(仅对实部进行操作) |
a.max()
返回
(1+0j)
;
a.min()
返回
(-1+0j)
|
| mean() | 数组
a
的平均值 |
a.mean()
返回
0.33333333333333331j (1j/3)
|
| prod() | 数组
a
中所有值的乘积 |
a.prod()
返回
-1j
,且
a.prod()
等于
a.cumprod()[-1]
|
| ptp() | 数组
a
的峰峰值,等同于
a.max()-a.min()
|
a.ptp()
返回
(2+0j)
|
| round() | 数组
a
的四舍五入值 |
exp(a).round()
返回
array([ 3.+0.j, 1.+1.j, 0.+0.j])
|
| std() | 数组
a
中元素的标准差 |
arange(2).std()
返回
0.5
|
| sum() | 数组
a
中所有值的和 |
a.sum()
返回
1j
,且
a.sum()
等于
a.cumsum()[-1]
|
| trace([n]) | 二维数组的对角线元素之和,如果提供
n
,则对偏移对角线求和 |
eye(10).trace()
返回
10
|
| var() | 数组
a
中元素的方差 |
arange(2).var()
返回
0.25
|
1.5 形状相关方法和属性
| 函数/属性 | 描述 | 示例 |
|---|---|---|
| flatten() |
将数组
a
的值转换为一维数组
|
eye(2).flatten()
返回
array([ 1., 0., 0., 1.])
|
| ndim |
数组
a
的维度数
|
eye(4, 5).ndim
返回
2
|
| repeat(n) |
将数组
a
复制
n
次并展平
|
eye(2).repeat(2)
返回
array([ 1., 1., 0., 0., 0., 0., 1., 1.])
|
| reshape(d1, d2, …) |
生成一个大小为
(d1, d2, ...)
的新数组
|
arange(4).reshape(2, 2)
返回
array([[0, 1], [2, 3]])
|
| resize(d1, d2, …) |
将当前数组的大小调整为
(d1, d2, ...)
|
a = arange(4)
;
a.resize(2, 2)
将
a
设置为
array([[0, 1], [2, 3]])
|
| shape |
表示数组
a
形状的元组
|
eye(3, 4).shape
返回
(3, 4)
|
| transpose() | 转置矩阵,等同于共轭但不否定虚部 |
eye(2, 3).transpose()
返回
array([[ 1., 0.], [ 0., 1.], [ 0., 0.]])
|
1.6 转换类方法
| 函数 | 描述 | 示例 |
|---|---|---|
| tofile(fname) | 将数组写入文件(二进制) |
eye(2).tofile('eye2.bin')
|
| fromfile(fid) | 从文件(二进制)中读取数组 |
a = fromfile(open('eye2.bin'))
|
| tolist() | 将数组转换为列表 |
eye(2).tolist()
返回
[[1.0, 0.0], [0.0, 1.0]]
|
2. 幻方示例
幻方是一种特殊的正方形,其每行、每列的元素之和都相等,且通常不允许数字重复。我们可以使用De la Loubère方法(也称为暹罗方法)来生成幻方,该方法仅适用于奇数阶的幻方。
2.1 算法步骤
-
将数字
1放在顶部中间的列。 - 后续数字沿对角线向上和向右放置。
- 如果超出正方形的边界,则将其环绕到最底行(如果超出顶部)或第一列(如果超出右侧)或两者。
- 如果单元格已被占用,则将数字向下移动一行(必要时进行环绕)。
2.2 代码实现
from pylab import *
def magicsq(n=3):
"""Returns a magic square of size n; n must be odd"""
if n % 2 != 1:
raise ValueError("Magic(n) requires n to be odd")
m, row, col = zeros([n, n]), 0, n//2
for num in range(1, n**2+1):
m[row, col] = num # fill the cell
col = (col+1) % n
row = (row-1) % n
if m[row, col]:
col = (col-1) % n
row = (row+2) % n
return m
def testmagicsq(m):
"""Returns True if m is a magic square."""
msum = sum(m[0, :])
return all(m.sum(0) == msum) and all(m.sum(1) == msum)
2.3 代码解释
-
在
magicsq函数中,使用for循环按照算法规则填充幻方。通过取模运算符%来处理边界情况,避免了复杂的条件判断。 -
在
testmagicsq函数中,通过比较每行和每列的和是否相等来判断是否为幻方。
2.4 测试示例
>>> exec(open('magic_square.py').read())
>>> a = eye(2, 3)
>>> a
array([[ 1., 0., 0.],
[ 0., 1., 0.]])
>>> a.sum(0)
array([ 1., 1., 0.])
>>> a.sum(1)
array([ 1., 1.])
>>> m = magicsq(5)
>>> m.sum(0)
array([ 65., 65., 65., 65., 65.])
>>> m.sum(1)
array([ 65., 65., 65., 65., 65.])
>>> testmagicsq(m)
True
通过上述测试可以看到,生成的幻方满足每行、每列的和都相等的条件。
3. 其他有用的数组函数
除了
ndarray
的属性和方法外,NumPy还提供了一些操作数组的函数,这些函数不属于
ndarray
对象类。可以使用以下代码查看所有这些函数:
import numpy
dir(numpy)
这些函数涵盖了多个领域,具体如下:
-
向量运算
:
convolve()
、
cross()
、
correlate()
和
vdot()
。
-
矩阵运算
:
diag()
和
trace()
。
-
统计函数
:
cov()
、
var()
、
std()
、
mean()
和
histogram()
。
-
金融函数
:
fv()
、
pv()
和
pmt()
。
-
多项式运算
:
polyadd()
、
polymul()
、
polydiv()
、
polyfit()
、
polyder()
、
polyint()
和
roots()
。
-
改变向量和矩阵大小和方向的操作
:
flipud()
、
fliplr()
和
rot90()
。
-
生成滤波窗口的函数
:
hamming()
、
hanning()
、
bartlett()
、
blackman()
和
kaiser()
。
3.1
numpy.diff
函数示例
>>> help(numpy.diff)
Help on function diff in module numpy.lib.function_base:
diff(a, n=1, axis=-1)
Calculate the n-th order discrete difference along given axis.
The first order difference is given by ``out[n] = a[n+1] - a[n]`` along
the given axis, higher order differences are calculated by using 'diff'
recursively.
Parameters
----------
a : array_like
Input array
n : int, optional
The number of times values are differenced.
axis : int, optional
The axis along which the difference is taken, default is the last
axis.
Returns
-------
diff : ndarray
The 'n' order differences. The shape of the output is the same as 'a'
except along 'axis' where the dimension is smaller by 'n'.
diff()
函数用于计算数组中两个连续元素之间的差值。在之前的示例中,如“Adding Arrows to a Graph”,以及可以修改朋友见面的示例来使用
diff()
函数替代列表推导式。
4. 数值分析与信号处理概述
数值分析和信号处理是许多科学领域(如数学、计算机科学、工程学等)中重要的主题。从简单的角度来看,数值分析关注能产生数值结果的算法,例如求解非线性方程的解、计算圆周率的十进制表示等。而信号处理则处理随时间变化的信号,包括信号的检测和滤波等。
虽然很多高校都开设了相关的本科课程,但即使没有工程或计算机科学背景,也能理解和运用这些方法和思想。对于有数值分析和信号处理基础的人来说,这里可以作为在Python中应用这些知识的起点;对于初学者,也能通过这里的介绍和示例,结合相关科学文献进一步学习。
5. NumPy的辅助函数
5.1
who()
函数
在交互式环境中工作时,我们会不断定义变量,很难记住定义了哪些变量以及它们的含义。
who()
函数可以打印出当前的NumPy数组列表。
>>> from pylab import *
>>> who()
Upper bound on total bytes = 0
>>> up, down = arange(10), arange(10, 0, -1)
>>> who()
Name Shape Bytes Type
===========================================================
up 10 40 int32
down 10 40 int32
Upper bound on total bytes = 80
5.2
lookfor()
函数
lookfor()
函数非常适合在文档字符串中进行搜索。例如,要查找执行数值积分的函数,可以使用以下代码:
>>> lookfor('integrate')
Search results for 'integrate'
------------------------------
numpy.trapz
Integrate along the given axis using the composite trapezoidal rule.
6. SciPy库介绍
6.1 SciPy概述
SciPy(http://www.scipy.org/)是一个用于Python的开源科学库,其理念类似于Octave - Forge(http://octave.sourceforge.net/)为GNU - Octave(http://www.octave.org)提供额外包,以及为MATLAB(http://www.mathworks.com)提供增强工具箱。SciPy构建在NumPy之上,因此需要NumPy才能正常工作。
6.2 SciPy的模块
SciPy被组织成多个模块,部分模块如下表所示:
| 模块 | 说明 |
| — | — |
| 未详细列出的模块 | 涵盖了数值分析、信号处理等多个领域的功能 |
7. 总结
本文介绍了NumPy数组的各种方法和属性,包括逻辑、索引、修改、数学、形状相关和转换等类别,通过详细的表格和示例代码展示了它们的使用方法。还讲解了幻方的生成算法及代码实现,以及NumPy中其他有用的数组函数。此外,对数值分析和信号处理的概念进行了概述,并介绍了NumPy的辅助函数
who()
和
lookfor()
,最后引入了SciPy库。
通过这些内容,我们可以利用Python中的NumPy和SciPy库进行更高效的数值计算和科学分析。在实际应用中,可以根据具体需求选择合适的函数和方法,对代码进行修改和扩展,以解决各种实际问题。
下面是一个简单的mermaid流程图,展示了幻方生成的主要步骤:
graph TD;
A[开始] --> B[初始化幻方矩阵、行和列];
B --> C[循环填充数字];
C --> D[填充当前单元格];
D --> E[计算下一个列和行的位置];
E --> F{下一个位置是否已占用};
F -- 是 --> G[调整列和行的位置];
F -- 否 --> C;
G --> C;
C --> H{是否填充完所有数字};
H -- 是 --> I[返回幻方矩阵];
H -- 否 --> C;
I --> J[结束];
同时,我们可以将NumPy数组方法和属性的类别总结成如下列表:
1. 逻辑类方法:
all()
、
any()
、
nonzero()
2. 索引类方法:
sort()
、
searchsorted()
3. 修改类方法:
clip()
、
compress()
、
fill()
4. 数学类方法:
cumprod()
、
cumsum()
、
real
、
imag
等
5. 形状相关方法和属性:
flatten()
、
ndim
、
repeat()
等
6. 转换类方法:
tofile()
、
fromfile()
、
tolist()
这些总结和图表有助于我们更好地理解和记忆相关知识,在实际编程中能够更快速地选择和使用合适的函数。
超级会员免费看
888

被折叠的 条评论
为什么被折叠?



