Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说用Python做科学计算(工具篇)——1.1. NumPy 数组对象[亲测有效],希望能够帮助你!!!。
目录
1.1.1. 什么是 NumPy 和 NumPy 数组?
NumPy 数组
Python对象: |
高级数字对象:整型、浮点型 容器:列表(无成本的插入和追加)、字典(快速查找) |
NumPy提供: |
用于多维数组的 Python 扩展包 更接近硬件(效率) 专为科学计算而设计(方便) 也称为面向矩阵的计算 |
>>>
>>> import numpy as np
>>> a = np.array([0, 1, 2, 3])
>>> a array([0, 1, 2, 3])
例如,一个包含以下内容的数组:
为什么有用:提供快速数值运算的内存高效容器。
In [1]: L = range(1000)
In [2]: %timeit [i**2 for i in L]
1000 loops, best of 3: 403 us per loop
In [3]: a = np.arange(1000)
In [4]: %timeit a**2
100000 loops, best of 3: 12.7 us per loop
NumPy 参考文档
In [5]: np.array?
String Form:<built-in function array> Docstring: array(object, dtype=None, copy=True, order=None, subok=False, ndmin=0, ...
>>>
>>> np.lookfor('create array') Search results for 'create array' --------------------------------- numpy.array Create an array. numpy.memmap Create a memory-map to an array stored in a *binary* file on disk.
In [6]: np.con*?
np.concatenate
np.conj
np.conjugate
np.convolve
导入约定
导入 numpy 的推荐约定是:
>>>
>>> import numpy as np
1.1.2. 创建数组
手动构建数组
>>>
>>> a = np.array([0, 1, 2, 3])
>>> a array([0, 1, 2, 3])
>>> a.ndim
1
>>> a.shape (4,)
>>> len(a)
4
>>>
>>> b = np.array([[0, 1, 2], [3, 4, 5]]) # 2 x 3 array
>>> b array([[0, 1, 2], [3, 4, 5]])
>>> b.ndim 2
>>> b.shape (2, 3)
>>> len(b) # returns the size of the first dimension 2
>>> c = np.array([[[1], [2]], [[3], [4]]])
>>> c array([[[1], [2]], [[3], [4]]])
>>> c.shape (2, 2, 1)
练习:简单数组
用于创建数组的函数
在实际中,我们不可能一个一个地手动输入数组元素......
>>>
>>> a = np.arange(10) # 0 .. n-1 (!)
>>> a array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> b = np.arange(1, 9, 2) # start, end (exclusive), step
>>> b array([1, 3, 5, 7])
>>>
>>> c = np.linspace(0, 1, 6) # start, end, num-points
>>> c array([0. , 0.2, 0.4, 0.6, 0.8, 1. ])
>>> d = np.linspace(0, 1, 5, endpoint=False)
>>> d array([0. , 0.2, 0.4, 0.6, 0.8])
>>>
>>> a = np.ones((3, 3)) # reminder: (3, 3) is a tuple
>>> a array([[1., 1., 1.], [1., 1., 1.], [1., 1., 1.]])
>>> b = np.zeros((2, 2))
>>> b array([[0., 0.], [0., 0.]])
>>> c = np.eye(3)
>>> c array([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]])
>>> d = np.diag(np.array([1, 2, 3, 4]))
>>> d array([[1, 0, 0, 0], [0, 2, 0, 0], [0, 0, 3, 0], [0, 0, 0, 4]])
>>>
>>> a = np.random.rand(4) # uniform in [0, 1]
>>> a array([ 0.95799151, 0.14222247, 0.08777354, 0.51887998])
>>> b = np.random.randn(4) # Gaussian
>>> b array([ 0.37544699, -0.11425369, -0.47616538, 1.79664113])
>>> np.random.seed(1234) # Setting the random seed
练习:使用函数创建数组
1.1.3. 基本数据类型
大家可能已经注意到,在某些情况下,数组元素以尾随点显示(例如2.vs 2)。这是由于使用的数据类型不同:
>>>
>>> a = np.array([1, 2, 3])
>>> a.dtype dtype('int64')
>>> b = np.array([1., 2., 3.])
>>> b.dtype dtype('float64')
不同的数据类型允许我们在内存中更紧凑地存储数据,但大多数时候我们只是使用浮点数。请注意,在上面的示例中,NumPy 会自动检测输入中的数据类型。
你可以明确指定所需的数据类型:
>>>
>>> c = np.array([1, 2, 3], dtype=float)
>>> c.dtype dtype('float64')
默认的数据类型是浮点型:
>>>
>>> a = np.ones((3, 3))
>>> a.dtype dtype('float64')
还有其他类型:
复杂的: |
>>> >>> d = np.array([1+2j, 3+4j, 5+6*1j]) >>> d.dtype dtype('complex128') |
布尔: |
>>> >>> e = np.array([True, False, False, True]) >>> e.dtype dtype('bool') |
字符串: |
>>> >>> f = np.array(['Bonjour', 'Hello', 'Hallo']) >>> f.dtype # <--- strings containing max. 7 letters dtype('S7') |
更多的: |
int32 int64 uint32 uint64 |
1.1.4. 基本可视化
现在我们有了第一个数据数组,我们将把它们可视化。
首先启动Spyder:
>>>
>>> %matplotlib
或者,从笔记本中,在笔记本中启用绘图:
>>>
>>> %matplotlib inline
绘图显示在笔记本中而不是在新窗口中。
>>>
import numpy as np
import matplotlib.pyplot as plt
#X轴,Y轴数据
x = np.arange(0,7)
y = [0.3,0.4,2,5,3,4.5,4]
plt.figure(figsize=(8,4)) #创建绘图对象
plt.plot(x,y,":ro",linewidth=1) #在当前绘图对象绘图(X轴,Y轴,蓝色虚线,线宽度)
plt.xlabel("Time(s)") #X轴标签
plt.ylabel("Volt") #Y轴标签
plt.title("Line plot") #图标题
plt.grid(True) #添加网格
plt.show() #显示图
from matplotlib import pyplot as mpl
import numpy as np data=np.clip(np.random.randn(5,5),-1,1) #生成随机数据,5行5列,最大值1,最小值-1
fig = plt.figure() # 第一个子图,按照默认配置
ax = fig.add_subplot(221) ax.imshow(data) # 第二个子图,使用自定义的colormap
ax = fig.add_subplot(222)
cmap=mpl.cm.cool #可以使用自定义的colormap
ax.imshow(data,cmap=cmap) # 第三个子图增加一个colorbar
ax = fig.add_subplot(223)
cmap=mpl.cm.hot #可以使用自定义的colormap
im=ax.imshow(data,cmap=cmap)
plt.colorbar(im) ## 第四个子图可以调整colorbar
ax = fig.add_subplot(224)
cmap = mpl.cm.winter
im=ax.imshow(data,cmap=cmap)
plt.colorbar(im,cmap=cmap, ticks=[-1,0,1]) plt.show()
三维图
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = Axes3D(fig)
X = np.arange(-4, 4, 0.25)
Y = np.arange(-4, 4, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='hot')
plt.show()
import numpy as np
import matplotlib.pyplot as plt
n = 8
X,Y = np.mgrid[0:n,0:n]
plt.quiver(X,Y)
plt.show()
练习:简单的可视化
1.1.5. 索引和切片
可以像其他 Python 序列(例如列表)一样访问和分配数组的项:
>>>
>>> a = np.arange(10)
>>> a array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> a[0], a[2], a[-1] (0, 2, 9)
索引从 0 开始,就像其他 Python 序列(和 C/C++)一样。相比之下,在 Fortran 或 Matlab 中,索引从 1 开始。
支持用于逆序列的常用 Python 语法:
>>>
>>> a[::-1]
array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
对于多维数组,索引是整数元组:
>>>
>>> a = np.diag(np.arange(3))
>>> a array([[0, 0, 0], [0, 1, 0], [0, 0, 2]])
>>> a[1, 1] 1
>>> a[2, 1] = 10 # 赋值第三行第二列元素为10
>>> a array([[ 0, 0, 0], [ 0, 1, 0], [ 0, 10, 2]])
>>> a[1] array([0, 1, 0])
笔记
切片:数组,像其他 Python 序列一样也可以切片:
>>>
>>> a = np.arange(10)
>>> a array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [15]:a[2:10:2] # [start:end:step]
Out[15]: array([2, 4, 6, 8])
请注意,不包括最后一个索引!:
a[:4]
array([0, 1, 2, 3])
不需要所有三个切片组件:默认情况下,start为 0, end为最后一个,step为 1:
>>>
>>> a[1:3]
array([1, 2])
>>> a[::2]
array([0, 2, 4, 6, 8])
>>> a[3:]
array([3, 4, 5, 6, 7, 8, 9])
NumPy 索引和切片的一个小插图
您还可以结合分配和切片:
>>>
>>> a = np.arange(10)
>>> a[5:] = 10
>>> a
array([ 0, 1, 2, 3, 4, 10, 10, 10, 10, 10])
>>> b = np.arange(5)
>>> a[5:] = b[::-1]
>>> a
array([0, 1, 2, 3, 4, 4, 3, 2, 1, 0])
练习:索引和切片
>>>
>>> np.arange(6) + np.arange(0, 51, 10)[:, np.newaxis]
array([[ 0, 1, 2, 3, 4, 5], [10, 11, 12, 13, 14, 15], [20, 21, 22, 23, 24, 25], [30, 31, 32, 33, 34, 35], [40, 41, 42, 43, 44, 45], [50, 51, 52, 53, 54, 55]])
练习:数组创建
创建以下数组(具有正确的数据类型):
[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 2], [1, 6, 1, 1]] [[0., 0., 0., 0., 0.], [2., 0., 0., 0., 0.], [0., 3., 0., 0., 0.], [0., 0., 4., 0., 0.], [0., 0., 0., 5., 0.], [0., 0., 0., 0., 6.]]
课程标准:每人 3 个陈述
提示:可以像访问列表一样访问单个数组元素,例如a[1]或。a[1, 2]
提示:检查 .doc 的文档字符串diag。
练习:用于创建数组的平铺
浏览 的文档np.tile,并使用此函数构造数组:
[[4, 3, 4, 3, 4, 3], [2, 1, 2, 1, 2, 1], [4, 3, 4, 3, 4, 3], [2, 1, 2, 1, 2, 1]]
1.1.6. 复制和查看
切片操作在原始数组上创建查看,这只是访问数组数据的一种方式。因此原始数组不会复制到内存中。你可以使用np.may_share_memory()检查两个数组是否共享同一个内存块。但是请注意,这使用了启发式方法,可能会误报。
修改查看时,原始数组也被修改:
>>>
>>> a = np.arange(10)
>>> a array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> b = a[::2]
>>> b array([0, 2, 4, 6, 8])
>>> np.may_share_memory(a, b) True
>>> b[0] = 12
>>> b array([12, 2, 4, 6, 8])
>>> a # (!) array([12, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> a = np.arange(10)
>>> c = a[::2].copy() # force a copy
>>> c[0] = 12
>>> a array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> np.may_share_memory(a, c) False
这种行为乍一看可能令人惊讶……但它可以节省内存和时间。
工作示例:素数筛
用筛子计算 0-99 之间的素数
>>>
>>> is_prime = np.ones((100,), dtype=bool)
>>>
>>> is_prime[:2] = 0
>>>
>>> N_max = int(np.sqrt(len(is_prime) - 1))
>>> for j in range(2, N_max + 1): ... is_prime[2*j::j] = False
1.1.7. 花式索引
NumPy 数组可以用切片索引,也可以用布尔或整数数组(掩码)索引。这种方法称为花式索引。它创建副本而不是查看。
使用布尔掩码
>>>
>>> np.random.seed(3)
>>> a = np.random.randint(0, 21, 15)
>>> a array([10, 3, 8, 0, 19, 10, 11, 9, 10, 6, 0, 20, 12, 7, 14])
>>> (a % 3 == 0) array([False, True, False, True, False, False, False, True, False, True, True, False, True, False, False])
>>> mask = (a % 3 == 0) >>> extract_from_a = a[mask] # or, a[a%3==0]
>>> extract_from_a # extract a sub-array with the mask array([ 3, 0, 9, 6, 0, 12])
使用掩码进行索引对于为子数组分配新值非常有用:
>>>
>>> a[a % 3 == 0] = -1
>>> a array([10, -1, 8, -1, 19, 10, 11, -1, 10, -1, -1, 20, -1, 7, 14])
用整数数组索引
>>>
>>> a = np.arange(0, 100, 10)
>>> a array([ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90])
可以使用整数数组进行索引,其中相同的索引重复多次:
>>>
>>> a[[2, 3, 2, 4, 2]] # note: [2, 3, 2, 4, 2] is a Python list array([20, 30, 20, 40, 20])
可以使用这种索引分配新值:
>>>
>>> a[[9, 7]] = -100
>>> a
array([ 0, 10, 20, 30, 40, 50, 60, -100, 80, -100])
当通过使用整数数组索引创建新数组时,新数组具有与整数数组相同的形状:
>>>
>>> a = np.arange(10)
>>> idx = np.array([[3, 4], [9, 7]])
>>> idx.shape (2, 2)
>>> a[idx]
array([[3, 4], [9, 7]])
下图说明了各种花哨的索引语法
练习:花式索引