3.9 大型数组�算¶
问题¶
ä½ éœ€è¦�在大数æ�®é›†(æ¯”å¦‚æ•°ç»„æˆ–ç½‘æ ¼)上é�¢æ‰§è¡Œè®¡ç®—。
解决方案¶
涉�到数组的��级�算�作,�以使用 NumPy 库。
NumPy 的一个主è¦�特å¾�是它会给Pythonæ��ä¾›ä¸€ä¸ªæ•°ç»„å¯¹è±¡ï¼Œç›¸æ¯”æ ‡å‡†çš„Python列表而已更适å�ˆç”¨æ�¥å�šæ•°å¦è¿�算。
下é�¢æ˜¯ä¸€ä¸ªç®€å�•çš„å°�例å�,å�‘ä½ å±•ç¤ºæ ‡å‡†åˆ—è¡¨å¯¹è±¡å’Œ NumPy 数组对象之间的差别:
>>> # Python lists
>>> x = [1, 2, 3, 4]
>>> y = [5, 6, 7, 8]
>>> x * 2
[1, 2, 3, 4, 1, 2, 3, 4]
>>> x + 10
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "int") to list
>>> x + y
[1, 2, 3, 4, 5, 6, 7, 8]
>>> # Numpy arrays
>>> import numpy as np
>>> ax = np.array([1, 2, 3, 4])
>>> ay = np.array([5, 6, 7, 8])
>>> ax * 2
array([2, 4, 6, 8])
>>> ax + 10
array([11, 12, 13, 14])
>>> ax + ay
array([ 6, 8, 10, 12])
>>> ax * ay
array([ 5, 12, 21, 32])
>>>
æ£å¦‚所è§�,两ç§�æ–¹æ¡ˆä¸æ•°ç»„的基本数å¦è¿�算结果并ä¸�相å�Œã€‚
特别的, NumPy ä¸çš„æ ‡é‡�è¿�ç®—(比如 ax * 2 或 ax + 10 )会作用在æ¯�ä¸€ä¸ªå…ƒç´ ä¸Šã€‚
å�¦å¤–,当两个æ“�ä½œæ•°éƒ½æ˜¯æ•°ç»„çš„æ—¶å€™æ‰§è¡Œå…ƒç´ å¯¹ç‰ä½�置计算,并最终生æˆ�一个新的数组。
å¯¹æ•´ä¸ªæ•°ç»„ä¸æ‰€æœ‰å…ƒç´ å�Œæ—¶æ‰§è¡Œæ•°å¦è¿�ç®—å�¯ä»¥ä½¿å¾—作用在整个数组上的函数è¿�算简å�•而å�ˆå¿«é€Ÿã€‚ æ¯”å¦‚ï¼Œå¦‚æžœä½ æƒ³è®¡ç®—å¤šé¡¹å¼�的值,å�¯ä»¥è¿™æ ·å�šï¼š
>>> def f(x):
... return 3*x**2 - 2*x + 7
...
>>> f(ax)
array([ 8, 15, 28, 47])
>>>
NumPy 还为数组æ“�作æ��供了大é‡�的通用函数,这些函数å�¯ä»¥ä½œä¸º math 模å�—ä¸ç±»ä¼¼å‡½æ•°çš„æ›¿ä»£ã€‚比如:
>>> np.sqrt(ax)
array([ 1. , 1.41421356, 1.73205081, 2. ])
>>> np.cos(ax)
array([ 0.54030231, -0.41614684, -0.9899925 , -0.65364362])
>>>
使用这些通用函数è¦�比循环数组并使用 math 模å�—ä¸çš„函数执行计算è¦�快的多。
å› æ¤ï¼Œå�ªè¦�有å�¯èƒ½çš„è¯�å°½é‡�选择 NumPy 的数组方案。
底层实现ä¸ï¼Œ NumPy 数组使用了C或者Fortranè¯è¨€çš„æœºåˆ¶åˆ†é…�内å˜ã€‚
也就是说,它们是一个é�žå¸¸å¤§çš„连ç»çš„å¹¶ç”±å�Œç±»åž‹æ•°æ�®ç»„æˆ�的内å˜åŒºåŸŸã€‚
æ‰€ä»¥ï¼Œä½ å�¯ä»¥æž„é€ ä¸€ä¸ªæ¯”æ™®é€šPython列表大的多的数组。
æ¯”å¦‚ï¼Œå¦‚æžœä½ æƒ³æž„é€ ä¸€ä¸ª10,000*10,000çš„æµ®ç‚¹æ•°äºŒç»´ç½‘æ ¼ï¼Œå¾ˆè½»æ�¾ï¼š
>>> grid = np.zeros(shape=(10000,10000), dtype=float)
>>> grid
array([[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.],
...,
[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.]])
>>>
所有的普通æ“�作还是会å�Œæ—¶ä½œç”¨åœ¨æ‰€æœ‰å…ƒç´ 上:
>>> grid += 10
>>> grid
array([[ 10., 10., 10., ..., 10., 10., 10.],
[ 10., 10., 10., ..., 10., 10., 10.],
[ 10., 10., 10., ..., 10., 10., 10.],
...,
[ 10., 10., 10., ..., 10., 10., 10.],
[ 10., 10., 10., ..., 10., 10., 10.],
[ 10., 10., 10., ..., 10., 10., 10.]])
>>> np.sin(grid)
array([[-0.54402111, -0.54402111, -0.54402111, ..., -0.54402111,
-0.54402111, -0.54402111],
[-0.54402111, -0.54402111, -0.54402111, ..., -0.54402111,
-0.54402111, -0.54402111],
[-0.54402111, -0.54402111, -0.54402111, ..., -0.54402111,
-0.54402111, -0.54402111],
...,
[-0.54402111, -0.54402111, -0.54402111, ..., -0.54402111,
-0.54402111, -0.54402111],
[-0.54402111, -0.54402111, -0.54402111, ..., -0.54402111,
-0.54402111, -0.54402111],
[-0.54402111, -0.54402111, -0.54402111, ..., -0.54402111,
-0.54402111, -0.54402111]])
>>>
关于 NumPy 有一点需�特别的主�,那就是它扩展Python列表的索引功能 - 特别是对于多维数组。
ä¸ºäº†è¯´æ˜Žæ¸…æ¥šï¼Œå…ˆæž„é€ ä¸€ä¸ªç®€å�•的二维数组并试ç�€å�šäº›è¯•验:
>>> a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
>>> a
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
>>> # Select row 1
>>> a[1]
array([5, 6, 7, 8])
>>> # Select column 1
>>> a[:,1]
array([ 2, 6, 10])
>>> # Select a subregion and change it
>>> a[1:3, 1:3]
array([[ 6, 7],
[10, 11]])
>>> a[1:3, 1:3] += 10
>>> a
array([[ 1, 2, 3, 4],
[ 5, 16, 17, 8],
[ 9, 20, 21, 12]])
>>> # Broadcast a row vector across an operation on all rows
>>> a + [100, 101, 102, 103]
array([[101, 103, 105, 107],
[105, 117, 119, 111],
[109, 121, 123, 115]])
>>> a
array([[ 1, 2, 3, 4],
[ 5, 16, 17, 8],
[ 9, 20, 21, 12]])
>>> # Conditional assignment on an array
>>> np.where(a < 10, a, 10)
array([[ 1, 2, 3, 4],
[ 5, 10, 10, 8],
[ 9, 10, 10, 10]])
>>>
讨论¶
NumPy 是Python领域ä¸å¾ˆå¤šç§‘å¦ä¸Žå·¥ç¨‹åº“的基础,å�Œæ—¶ä¹Ÿæ˜¯è¢«å¹¿æ³›ä½¿ç”¨çš„æœ€å¤§æœ€å¤�æ�‚的模å�—。
å�³ä¾¿å¦‚æ¤ï¼Œåœ¨åˆšå¼€å§‹çš„æ—¶å€™é€šè¿‡ä¸€äº›ç®€å�•的例å�和玩具程åº�也能帮我们完æˆ�一些有趣的事情。
通常我们导入 NumPy 模å�—的时候会使用è¯å�¥ import numpy as np 。
è¿™æ ·çš„è¯�ä½ å°±ä¸�用å†�ä½ çš„ç¨‹åº�里é�¢ä¸€é��é��的敲入 numpy ,å�ªéœ€è¦�输入 np 就行了,节çœ�了ä¸�少时间。
如果想获å�–更多的信æ�¯ï¼Œä½ 当然得去 NumPy 官网逛逛了,网å�€æ˜¯ï¼š http://www.numpy.org